I am using IdentityServer4.
I want to add other custom claims to access token but I'm unable to do this. I have modified Quickstart5 and added ASP.NET Identity Core and the custom claims via ProfileService as suggested by Coemgen below.
You can download my code here: [zip package][3]. (It is based on: Quickstart5 with ASP.NET Identity Core and added claims via ProfileService).
Issue: GetProfileDataAsync does not executed.
Two parties are involved in an access token request: the client, who requests the token, and the resource (Web API) that accepts the token. The aud claim in a token indicates the resource that the token is intended for (its audience). Clients use the token but shouldn't understand or attempt to parse it.
To get a new access token, you send the refresh token to the token endpoint. This will result in a new token response containing a new access token and its expiration and potentially also a new refresh token depending on the client configuration (see above).
IdentityServer emits claims about users and clients into tokens. You are in full control of which claims you want to emit, in which situations you want to emit those claims, and where to retrieve those claims from.
You should implement your own ProfileService
. Have a look in this post which I followed when I implemented the same:
https://damienbod.com/2016/11/18/extending-identity-in-identityserver4-to-manage-users-in-asp-net-core/
Here is an example of my own implementation:
public class ProfileService : IProfileService { protected UserManager<ApplicationUser> _userManager; public ProfileService(UserManager<ApplicationUser> userManager) { _userManager = userManager; } public async Task GetProfileDataAsync(ProfileDataRequestContext context) { //>Processing var user = await _userManager.GetUserAsync(context.Subject); var claims = new List<Claim> { new Claim("FullName", user.FullName), }; context.IssuedClaims.AddRange(claims); } public async Task IsActiveAsync(IsActiveContext context) { //>Processing var user = await _userManager.GetUserAsync(context.Subject); context.IsActive = (user != null) && user.IsActive; } }
Don't forget to configure the service in your Startup.cs (via this answer)
services.AddIdentityServer() .AddProfileService<ProfileService>();
although you have configured your available Identity resources correctly (both standard & custom), you also need to explicitly define which ones are a necessity when calling your api resource. In order to define this you must go to your Config.cs
class on ExampleIdentityServer
project and provide a third argument like on the new ApiResouirce
constructor. Only those will be included into the access_token
// scopes define the API resources in your system public static IEnumerable<ApiResource> GetApiResources() { return new List<ApiResource> { new ApiResource("api1", "My API", new[] { JwtClaimTypes.Subject, JwtClaimTypes.Email, JwtClaimTypes.Phone, etc... }) }; }
In essence this means that I got my identity claims configured for my organization but there may be more than one APIs involved and not all of the APIs make use of all available profile claims. This also means that these will be present inside your ClaimsPrincipal
all the rest can still be accessed through the "userinfo" endpoint as a normal http call.
If you chose to enable refresh tokens via AllowOfflineAccess = true
, you may experience the same behavior upon refreshing the access_token "GetProfileDataAsync does not executed!". So the claims inside the access_token stay the same although you get a new access_token with updated lifetime. If that is the case you can force them to always refresh from the Profile service by setting UpdateAccessTokenClaimsOnRefresh=true
on the client configuration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With