Home > Software engineering >  service to service does not accept a token from IdentityServer
service to service does not accept a token from IdentityServer

Time:12-15

i am learning ASP.NET and IndentityServer4 I made a server that generates a token for me according to the tutorial, I get it both from the postman and from the controller of my "client" but when I try to make a request to the "backend" where authorization is required, I get an error 401, I don't understand what I did wrong

IdentityServer

public static class Configuration
{
    public static IEnumerable<ApiScope> ApiScopes => new List<ApiScope> 
    { 
        new ApiScope("NotesWebAPI", "Web API") 
    };

    public static IEnumerable<IdentityResource> IdentityResources =>
        new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
        };

    public static IEnumerable<ApiResource> ApiResources =>
        new List<ApiResource>
        {
            new ApiResource("NotesWebAPI", "Web API", new []{ JwtClaimTypes.Name })
            {
                Scopes = { "NotesWebAPI" }
            }
        };

    public static IEnumerable<Client> Clients =>
        new List<Client>
        {
            new Client
        {
            ClientId = "client_id",
            ClientSecrets = { new Secret("client_secret".ToSha256()) },

            AllowedGrantTypes = GrantTypes.ClientCredentials,
            AllowedScopes =
            {
                "NotesWebAPI",
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile
            }
        },
        };
}

Starttup IndetityServer

public class Startup
{
    IConfiguration AppConfiguration { get; }
    public Startup(IConfiguration config)
    {
        AppConfiguration = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentity<AppUser, IdentityRole>(config =>
        {
            config.Password.RequiredLength = 6;
            config.Password.RequireDigit = false;
            config.Password.RequireNonAlphanumeric = false;
            config.Password.RequireUppercase = false;
            config.Password.RequireLowercase = false;
        })
            .AddEntityFrameworkStores<AuthDbContext>()
            .AddDefaultTokenProviders();

        services.AddDbContext<AuthDbContext>(options =>
            options.UseSqlServer(
                AppConfiguration.GetConnectionString("DefaultConnection")));

        services.AddIdentityServer()
            .AddAspNetIdentity<AppUser>()
            .AddInMemoryApiResources(Configuration.ApiResources)
            .AddInMemoryIdentityResources(Configuration.IdentityResources)
            .AddInMemoryApiScopes(Configuration.ApiScopes)
            .AddInMemoryClients(Configuration.Clients)
            .AddDeveloperSigningCredential();

        services.ConfigureApplicationCookie(config =>
        {
            config.Cookie.Name = "Notes.Identity.Cookie";
            //config.LoginPath = "/Auth/Login";
            //config.LogoutPath = "/Auth/Logout";
        });

        services.AddControllersWithViews();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseStaticFiles(new StaticFileOptions
        {
            FileProvider = new PhysicalFileProvider(
                Path.Combine(env.ContentRootPath, "Styles")),
            RequestPath = "/styles"
        });

        app.UseRouting();
        app.UseIdentityServer();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
}

my "backend"

private IConfiguration Configuration { get; }

    public Startup(IConfiguration config)
    {
        Configuration = config;
    }

    
    public void ConfigureServices(IServiceCollection services)
    {

        services.AddAutoMapper(config =>
        {
            config.AddProfile(new AssemblyMappingProfile(Assembly.GetExecutingAssembly()));
            config.AddProfile(new AssemblyMappingProfile(typeof(INotesDbContext).Assembly));
        });
        services.AddApplication();
        services.AddPersistence(Configuration);
        services.AddControllers();
        services.AddCors(config =>
        {
            config.AddPolicy("DefaultPolicy",
                builder =>
                builder
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());
        });

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, config =>
            {
                config.TokenValidationParameters = new TokenValidationParameters
                {
                    ClockSkew = TimeSpan.FromMinutes(1),
                    ValidateAudience = false
                };

                config.Authority = "https://localhost:5001";
                config.Audience = "NotesWebAPI";
                //config.Audience = "https://localhost:5001";
            });
    }

  
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseCustomExceptionHandler();
        app.UseRouting();
        app.UseHttpsRedirection();

        app.UseCors("DefaultPolicy");

        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

"client" controller

[Route("[action]")]
    public async Task<IActionResult> GetNotes()
    {
        var authClient = _httpClientFactory.CreateClient();

        var discoverDocument = await authClient.GetDiscoveryDocumentAsync("http://localhost:5000");

        var tokenResponse = await authClient.RequestClientCredentialsTokenAsync(
            new ClientCredentialsTokenRequest
            {
                Address = discoverDocument.TokenEndpoint,
                ClientId = "client_id",
                ClientSecret = "client_secret",
                Scope = "NotesWebAPI",
            });

        var requestClient = _httpClientFactory.CreateClient();

        requestClient.SetBearerToken(tokenResponse.AccessToken);

        var responce = await requestClient.GetAsync("http://localhost:1321/api/note");

        if (!responce.IsSuccessStatusCode)
        {
            ViewBag.Message = responce.StatusCode.ToString();
            return View();
        }

        var message = await responce.Content.ReadAsStringAsync();
        ViewBag.Message = message;
        return View();
    }

UPDATED: If I send a request through Postman then it goes through, it doesn't go through only the "client" request

CodePudding user response:

One thing you can do to troubleshoot API authentication errors is to enable this flag:

.AddJwtBearer(opt =>
{
    ...
    opt.IncludeErrorDetails = true;

Then when it fails, it will add the WWW-Authenticate response header, that can give you some clues about the problem:

HTTP/1.1 401 Unauthorized
Date: Sun, 02 Aug 2020 11:19:06 GMT
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
  • Related