i want to get custom claims via the userinfo endpoint. That works too but all of the custom claims are in access token too. I understand it in that way, that there is a possibility where i can put one or two claims (like email or name) in the access token and all of the other claims (given_name,...) are accessed via the userinfo endpoint. (and they are not in the access token)
my ProfileService is looking like that:
public class ProfileService : IProfileService
{
private readonly IUserClaimsPrincipalFactory<CustomUser> _claimsFactory;
private readonly UserManager<CustomUser> _userManager;
public ProfileService(UserManager<CustomUser> userManager, IUserClaimsPrincipalFactory<CustomUser> claimsFactory)
{
_claimsFactory = claimsFactory;
_userManager = userManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var claims = principal.Claims.ToList();
claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
claims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
context.IssuedClaims = claims;
}
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
context.IsActive = user != null;
}
}
this is my config.cs file:
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API", new [] {JwtClaimTypes.Name })
};
}
new Client
{
ClientId = "xxx",
ClientName = "xxx",
//AccessTokenType = AccessTokenType.Reference,
AccessTokenType = AccessTokenType.Jwt,
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
RedirectUris = { "http://localhost:4200/home" },
PostLogoutRedirectUris = { "http://localhost:4200/unauthorized" },
AllowedCorsOrigins = { "http://localhost:4200" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api1"
}
}
};
Did i missunderstand it?
GetProfileDataAsync
is called twice, but with a different context.
Context.Caller
= ClaimsProviderAccessToken.Context.Caller
= UserInfoEndpoint.Please note that for both contexts the requested claims differ.
If you want to add claims for the identity only, you can either configure identityserver to include these claims by adding these to the filter (IdentityResource), in which case you won't need to add additional claims in GetProfileDataAsync
at all. Or in case you want to add a specific claim, check the current context.
So in GetProfileDataAsync
you could have something like the following:
if (Context.Caller == "UserInfoEndpoint")
claims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
This should add the claim to the userinfo only.