简体   繁体   中英

ASP.NET Identity Role claims missing

I'm logging in via Google using Duende IdentityServer, which is also configured to use ASP.NET Identity for user roles etc.

Google IdentityServer Config:

            .AddGoogle(options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                options.ClientId = "redacted"
                options.ClientSecret = "redacted";

            });

Blazor UI Auth config:

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})

    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme,
        options =>
        {
            options.Authority = "myidentityserverurl";

            options.ClientId = "web2";
            options.ClientSecret = "secret";
            options.UsePkce = true;
            options.ResponseType = "code";            
            options.Scope.Add("api1");
            options.Scope.Add("roles");
            options.ClaimActions.MapUniqueJsonKey("role", "role");
            options.ClaimActions.MapUniqueJsonKey("roles", "role");

            options.TokenValidationParameters = new TokenValidationParameters
            {
                RoleClaimType = JwtClaimTypes.Role,
                ValidateAudience = false
            };
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;
        });

API auth config:

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer(options =>
    {        
        options.Authority = "myidentityserverurl";
        options.Audience = "api1";

        options.TokenValidationParameters = new TokenValidationParameters
        {
            RoleClaimType = JwtClaimTypes.Role,
            ValidateAudience = false
        };
    });

I have a Blazor UI client which can successfully login via Google, which gives me back a Cookie, an access_token and an id_token.

The access_token returned from a Google login does not have any role claims from ASP.NET Identity, either from within Blazor or from Postman.

If I call /connect/userinfo in IdentityServer after logging in via google, I get the role I'm in as expected:

{
    "sub": "subhere",
    "name": "myname",
    "role": "SystemAdministrator",
    "preferred_username": "uuid from google"
}

In the Blazor app, if I get the claims from httpContextAccessor.HttpContext.User.Claims I get my role claim as expected.

If I make a call to my API using the access token issued as part of the login to the UI, and get the claims like so:

    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }

I don't have any role claim at all here. And likewise no role claim in the bearer token in Postman after logging in via Google.

Here are the claims from the API, missing my role claim:

[
  {
    "type": "iss",
    "value": "myidentityserverurl"
  },
  {
    "type": "nbf",
    "value": "1653401427"
  },
  {
    "type": "iat",
    "value": "1653401427"
  },
  {
    "type": "exp",
    "value": "1653405027"
  },
  {
    "type": "aud",
    "value": "https://myidentityserverurl/resources"
  },
  {
    "type": "scope",
    "value": "openid"
  },
  {
    "type": "scope",
    "value": "profile"
  },
  {
    "type": "scope",
    "value": "api1"
  },
  {
    "type": "scope",
    "value": "roles"
  },
  {
    "type": "http://schemas.microsoft.com/claims/authnmethodsreferences",
    "value": "external"
  },
  {
    "type": "client_id",
    "value": "web2"
  },
  {
    "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
    "value": "uuidhere"
  },
  {
    "type": "auth_time",
    "value": "1653401425"
  },
  {
    "type": "http://schemas.microsoft.com/identity/claims/identityprovider",
    "value": "Google"
  },
  {
    "type": "sid",
    "value": "A9E0A3B55D35FDAE3A7DCA0126C34E75"
  },
  {
    "type": "jti",
    "value": "43C218D3076EA595B4647CD7B369C405"
  }
]

I have been trying for a few days to fix and I've run out of ideas. I think I'm missing something fundamental here.

I think you could read the document related: http://docs.identityserver.io/en/latest/reference/profileservice.html#profile-service

and try as below:

public class ProfileServices : IProfileService
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<ApplicationRole> _roleManager;
        public ProfileServices(
            UserManager<ApplicationUser> userManager,
            RoleManager<ApplicationRole> roleManager)
        {
            _userManager = userManager;
            _roleManager = roleManager;
        }
 
        public async Task<List<Claim>> GetClaimsFromUserAsync(ApplicationUser user)
        {
            var claims = new List<Claim> {
                new Claim(JwtClaimTypes.Subject,user.Id.ToString()),
                new Claim(JwtClaimTypes.PreferredUserName,user.UserName)
            };
 
            var role = await _userManager.GetRolesAsync(user);
            role.ToList().ForEach(f =>
            {
                claims.Add(new Claim(JwtClaimTypes.Role, f));
            });    
            
           
            return claims;
        }
 
        
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
            var user = await _userManager.FindByIdAsync(subjectId);
            context.IssuedClaims =await GetClaimsFromUserAsync(user);
        }
 
        
        public async Task IsActiveAsync(IsActiveContext context)
        {
            var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
            var user = await _userManager.FindByIdAsync(subjectId);
            context.IsActive = user != null; 
        }
    }

Regist it in startup.cs:

services.AddScoped<IProfileService, ProfileService>();

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