Identityserver4: Adding Custom Default Claims to Token for client_credentials granttype

Created on 11 May 2017  路  21Comments  路  Source: IdentityServer/IdentityServer4

Is there currently a way to add custom default claims to client like we can do to the user profile though IProfileService ? This should be a useful feature

question

Most helpful comment

Don't think we have docs for it - you need to implement this

https://github.com/IdentityServer/IdentityServer4/blob/dev/src/IdentityServer4/Validation/Interfaces/ICustomTokenRequestValidator.cs

and add it to DI.

You can then add client claims on the context dynamically. Give it a try.

All 21 comments

you can configure the client claims on the client object - or add them dynamically using a custom token request validator

But how do i write a custom token request validator? Any examples or references? no i do not want to include it in the object.
I cant find how to write a custom request validator in the docs. can you point me to the resource?

Don't think we have docs for it - you need to implement this

https://github.com/IdentityServer/IdentityServer4/blob/dev/src/IdentityServer4/Validation/Interfaces/ICustomTokenRequestValidator.cs

and add it to DI.

You can then add client claims on the context dynamically. Give it a try.

Great Thanks. IT worked a charm.

hi @yehonathan , @leastprivilege

I found this quite helpful, but I need to go further in my case..

If I would like to attach a custom claim to a client (this coming from the client itself, after successful authorization).. how could I achieve this? how could I get this info on ids?
For example, in _/connect/token_ I don't see any extra params which client could post, or could we use _acr_values_ for that? Could you recommend something?

Thanks!

Actually I realized that I could inspect the extra params via the "Raw" property of the ValidatedTokenRequest.. Unfortunately when I add new claims here, they are not showing up in the access token on client side.. not sure what I am missing

Well, I discovered that context.Result.ValidatedRequest.ClientClaims should be used instead of context.Result.ValidatedRequest.Client.Claims .. could anybody confirm that this is how it should work?

ClientClaims adds prefix "client_" to custom claims. So crazy.

And ClientClaimsPrefix controls that

@leastprivilege
@brockallen

I apologize if I ask this here and not via Stackoverflow, but this might be related to this closed issue discussion. Possibly added for documentation.

I have an API (A) and has been authenticated using ResourceOwnerPasswordAndClientCredentials. I get the access_token as well as profile claims with subject. On this API (A), I would like to call other API (B) using client_credentials, however, I also need to pass the subject or some other unique identifier so API (B) knows who is the subject.

I use new TokenClient(...) from the API (A) to call the API (B).

[Authorize,HttpPost,Route("myapi2")]
public async Task<IActionResult> MyApi2()
{
    var client = new TokenClient(_settings.TokenEndpoint, "client2api", "secret");
    var token = await client.RequestClientCredentialsAsync(scope: "myapi");
    return Ok(token);
}

I manage to get the access_token and manage to add custom claims. But I cannot get the subject of the API (A). Here is the customer request validator. I understand client_credentials itself has no user. Am I doing the right way here.

    public class CustomClaimInjection : ICustomTokenRequestValidator
    {
        private readonly HttpContext _httpContext;

        public CustomClaimInjection(IHttpContextAccessor contextAccessor)
        {
            _httpContext = contextAccessor.HttpContext;
        }

        public Task ValidateAsync(CustomTokenRequestValidationContext context)
        {
            // THIS ONE. HOW TO GET THE SUB. THIS ALWAYS NULL.
            var sub = _httpContext.User.FindFirst(JwtRegisteredClaimNames.Sub)?.Value;

            var client = context.Result.ValidatedRequest.Client;
            client.Claims.Add(new Claim("sub", sub));  // this will be [client_sub]

            return Task.FromResult(0);
        }
    }

This is not how it works.

The "sub of the client" would be the client_id claim.

@leastprivilege

My bad, duh... I should not use ICustomTokenRequestValidator.
I manage to resolve it by using IExtensionGrantValidator. All works like a charm. Thanks.

It's all here in the documentation http://docs.identityserver.io/en/dev/topics/extension_grants.html

    // get user's identity
    var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;
    context.Result = new GrantValidationResult(sub, GrantType);

should ICustomTokenRequestValidator be registered as Singleton or Scoped?

@drowhunter use,

services.AddTransient<ICustomTokenRequestValidator, [your implementation]>();

thanks.

@leastprivilege

The "sub of the client" would be the client_id claim.

I was trawling through the JWT, OAuth2, and OIDC specifications and I can't see client_id defined by any of them except for use as a parameter when using client authentication. I noticed that IdentityServer4 seems to be adding client_id as a claim by default (I have no problem with this), but is it spec'd out anywhere? The IS4 docs only make a few references to a client_id claim, such as https://hts.readthedocs.io/en/latest/quickstarts/1_client_credentials.html

By default an access token will contain claims about the scope, lifetime (nbf and exp), the client ID (client_id) and the issuer name (iss).

Is there any risk the behaviour of the IS4-added client_id claim might change in future? (Either in a point-release, major release, or a hypothetical IS5?)

There is no spec about access tokens and their claim types. We made this decision at some point.

This is not how it works.

The "sub of the client" would be the client_id claim.

Sorry for adding to this closed issue but I would like a small clarification here.

Does this mean that sub is not set for client_credentials flow?

Does this mean that sub is not set for client_credentials flow?

Correct. Use client_id to know the calling app.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings