简体   繁体   中英

HttpContext User claims are empty

I previously have a working project that uses IdentityServer and.Net Core 2.2

I recently did an upgrade on the project's.Net version from Core 2.2 to.Net 5. Also updated every packages into the latest version. Did some tweaks on my code and finally got rid of all the errors. I'm testing my Identity server functionality on my WEB API, and for some reason, the HttpContext.User.Claims return empty.

Here's my code for it.

public Guid? CurrentUserId
{
    get
    {

       var claimNameIdentifier = User.Claims.FirstOrDefault(a => a.Type == ClaimTypes.NameIdentifier)?.Value;
       return claimNameIdentifier != null ? Guid.Parse(claimNameIdentifier) : (Guid?)null;
    }
}

I have this on a base controller to be implemented by my endpoint controllers to get the user id on the JWT accessing my endpoint. Not sure if this is due to the updates as this was working before.

Here's my Config for my identity server

public static IEnumerable<IdentityResource>  IdentityResources =>
        new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile()
        };
    public static IEnumerable<ApiResource> ApiResources =>
       new List<ApiResource>
       {
           new ApiResource
            {
               Name = "ssi.api",
               DisplayName = "Standing Settlement Instructions API"
            }
       };

    public static IEnumerable<ApiScope> ApiScopes =>
        new List<ApiScope>
        {
            new ApiScope
            {
               Name = "ssi.api",
               DisplayName = "Standing Settlement Instructions API"
            
            }
        };

    public static IEnumerable<Client> Clients =>
        new List<Client>
        {
            new Client
            {
                ClientId = "ssi.front",
                ClientName = "SSI Client",
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                // secret for authentication
                ClientSecrets =
                {
                   new Secret("my secret".Sha256())
                },
                // scopes that client has access to
                AllowedScopes = {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "ssi.api",
                    JwtClaimTypes.Role
                },
                AccessTokenLifetime = 14400,
                AllowOfflineAccess = true,
            }
        };

Here's how my ConfigureServices look like:

// Database
   services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer("Server=localhost; Database = SsiDB; Integrated Security = SSPI; MultipleActiveResultSets=true;"));
    #region Identity
    services.AddIdentity<User, Role>(options =>
    {
        options.Password.RequiredLength = 8;
        options.Password.RequireDigit = false;
        options.Password.RequireLowercase = false;
        options.Password.RequireNonAlphanumeric = false;
        options.Password.RequireUppercase = false;
        options.User.RequireUniqueEmail = true;
    })
    .AddRoles<Role>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

    var identityBuilder = services.AddIdentityServer()
        .AddInMemoryPersistedGrants()
        .AddInMemoryClients(IdentityConfig.Clients)
        .AddInMemoryApiResources(IdentityConfig.ApiResources)
        .AddInMemoryApiScopes(IdentityConfig.ApiScopes)
        .AddAspNetIdentity<User>();

    identityBuilder.Services.AddTransient<IResourceOwnerPasswordValidator, OwnerPasswordValidator>();
    identityBuilder.Services.AddTransient<IProfileService, IdentityProfileService>();
    identityBuilder.AddSigningCredential(new X509Certificate2("StandingSettlementInstructionsIdentityAuth.pfx", "", X509KeyStorageFlags.MachineKeySet)); //release
    #endregion

    services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = appSettings.ApiUrl;
        options.Audience = "ssi.api";
        options.RequireHttpsMetadata = false;
    });

And this is my configure

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
        app.UseHsts();
        string appDataPath = Directory.GetCurrentDirectory() + @"\AppData";

        if (!Directory.Exists(appDataPath))
            Directory.CreateDirectory(appDataPath);

        app.UseSwaggerUI(o =>
        {
            o.DocumentTitle = "Standing Settlement Instructions Api Documentation";
            o.RoutePrefix = "api-docs";
            o.SwaggerEndpoint("/swagger/v1/swagger.json", "Version 1");
        });
        app.UseSwagger();

        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseCors("CorsPolicy");
        app.UseIdentityServer();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapHub<NotificationHubService>("/NotificationHubService");
        });

        app.Run((context =>
        {
            context.Response.Redirect("api-docs");
            return Task.CompletedTask;
        }));
    }

Things I tried:

  • added this on the ConfigureService services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); and use it on my base controller. same result
  • Re-arrange the calls on Configure method based on some google searches
  • Added claims on API Resource and API Scopes. Same result

Some observation. Accessing localhost/.well-known/openid-configuration displays empty supported claims, when I added claims on either API Resource or API Scopes, it does appear in there but still getting the same issue when extracting claims. Still empty.

Any help will be highly appreciated. Been pulling my hair out on this. Thanks!

The first step to debug claims issues is to actually look at what does the access token actually contain? Use a tool like https://jwt.io/ to do that.

Then Microsoft and IdentityServer have different opinion on what the name of the claims should be, so you need to point out, which claim is the name claim, by using:

    .AddJwtBearer(opt =>
    {
        opt.TokenValidationParameters.RoleClaimType = "roles";
        opt.TokenValidationParameters.NameClaimType = "name";

        ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM