Wednesday, April 1, 2020

IdentityServer4: Adding Additional Claims to the Token

In this post let's see how we can additional claims to the token. This can be either creating tokens or when handling requests to the userinfo or introspection endpoints. In addition, let's have a look at how we can add in additional claims to a client ASP.NET Core application.

IS4, provides an interface IProfileService which we can implement to add in additional claims. It's basically going to be something like this.
public class ProfileService : IProfileService
{
    public ProfileService()
    {
    }
 
    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        // Get all the claims you need to add into the token by context.Subject
        // Set it to context.IssuedClaims
        // This is expected to be populated
    }
 
    public async Task IsActiveAsync(IsActiveContext context)
    {
        // Check context.Subject is allowed to retrieve additional claims
        // Based on that set context.IsActive
        // This is expected to be set
    }
}
So here one of the important things is, context contains a property named Caller, as the name suggests that determines what triggered this call. Unfortunately, it's a type of string, but there is a set of constants in ID4, that you can use.
public static class ProfileDataCallers
{
    public const string UserInfoEndpoint = "UserInfoEndpoint";
    public const string ClaimsProviderIdentityToken = "ClaimsProviderIdentityToken";
    public const string ClaimsProviderAccessToken = "ClaimsProviderAccessToken";
}
So by checking the context.Caller, you can decide which claims you want to include based on the Caller.

Plugging in ProfileService to IdentityServer is quite simple, we can just do as follows when we are adding IdentityServer.
AddProfileService
It's pretty neat!

Sometimes, you might face a scenario, you want to add in additional claims, not when the token issued from ID4, but from the client ASP.NET Core application. Basically, this is how we protect an ASP.NET Core Web API application with an ID4.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // set Authority and additional options
    });
Instead of using AddJwtBearer, we can use AddIdentityServerAuthentication authentication handler which is available in IdentityServer4.AccessTokenValidation NuGet package.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(options =>
    {
        // set Authority and additional options

        options.JwtBearerEvents.OnTokenValidated = OnTokenValidated;
    });
There we can handle the OnTokenValidated event. This will be invoked after the security token has passed validation and a ClaimsIdentity has been generated. So here also we can additional claims. But there is a downside with this approach, each time the API is being called with the token, this will get invoked.
private async Task OnTokenValidated(TokenValidatedContext context)
{
    // var identity = context.Principal.Identity as ClaimsIdentity;
    // identity.AddClaim(new Claim("X","Y");
}
So hope this bit of information helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment