Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a custom claim in an extension grant type only

I want to add a custom claim in my extension grant type. and my code is like the following in my class that implement IExtensionGrantValidator, but the resulting token from this doesn't contain the added custome_claim

        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
        var userToken = context.Request.Raw.Get("token");

        if (string.IsNullOrEmpty(userToken))
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        var result = await _validator.ValidateAccessTokenAsync(userToken);
        if (result.IsError)
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        var sub = result.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;

        context.Result = new GrantValidationResult(sub, "graph_delegation", new List<Claim> { new Claim("custome_claim", "Hello from the custom grant") });
    }
like image 254
Mostafa Abd El Razek Avatar asked May 31 '18 15:05

Mostafa Abd El Razek


1 Answers

The process consists of three parts and is identical for issuing any access token with custom claims, not only for extension grant:

Firstly the claim has to be requested by the client using an appropriate scope. On the Identity Server side GetApiResources() method must add that claim type into the appropriate scope.

    public static IEnumerable<ApiResource> GetApiResources(){
        return new List<ApiResource>{
             new ApiResource{
                    Name = "API 1",
                    DisplayName = "API 1",
                    Scopes = {
                        new Scope {
                            Name = "my-api",
                            UserClaims =  {
                                JwtClaimTypes.SessionId,
                                JwtClaimTypes.Role,
                                Constants.TenantIdClaimType,
                                "custom_claim" }
                        }
                    }
                }               
            };
      }

Secondly the claim has to be issued somehow -- one way is to use GrantValidationResult constructor, as described in the original post above, to put it in.

And finally the requested claim should be added to the IssuedClaims collection for the token. That is the job for a ProfileService implementation. A custom ProfileService should be implemented and registered in IdSrv startup as the following:

    services.AddIdentityServer()
        ***
        .AddInMemoryApiResources(GetApiResources())
        .AddExtensionGrantValidator<DelegationGrantValidator>()
        .AddProfileService<ExtendedProfileService>();

Where in

    public override Task GetProfileDataAsync(ProfileDataRequestContext context)

the row: context.AddRequestedClaims(context.Subject.Claims); will do the job. It's not necessary to implement IProfileService from scratch, but enough to derive an existing one and override only one method.

like image 147
d_f Avatar answered Oct 29 '22 18:10

d_f