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") });
}
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.
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