IdentityServer4: Add Custom default Claim to Client Principal for Client_Credential Granttype

flexxxit picture flexxxit · May 10, 2017 · Viewed 7.7k times · Source

I am using IdentityServer4 and I am trying to add a custom default claim to my CLIENT when the token is created. This is possible if i use the implicit flow and IProfileService like shown below.

public class MyProfileService : IProfileService
{
    public MyProfileService()
    {

    }
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var claims = new List<Claim>
        {
            new Claim("DemoClaimType", "DemoClaimValue")
        };
        context.IssuedClaims = claims;
        return Task.FromResult(0);
    }
    public Task IsActiveAsync(IsActiveContext context)
    {
        context.IsActive = true;
        return Task.FromResult(0);
    }
}

And in my startup

services.AddIdentityServer()
            .AddProfileService<MyProfileService>()

However this does not work with my client with client_credential granttype since it seems cannot request OpenID scopes in client credentials flow. It turns out Iprofileservice like the name implies works for Identity Resources where the OpenId scopes like profile is valid. since am unable to request profile scopes with client_credential grant type GetProfileDataAsync never gets called.

Since am working only with clients and no users I need a way to inject claims into the token without having to add them to the client object like below

    new Client
{
    ClientId = "myclient",
    ClientName = "My Client",
    AllowedGrantTypes = GrantTypes.ClientCredentials,
    ClientSecrets = {new Secret("secret".Sha256())},
    AllowedScopes = new List<string> {"api"},                    
    AllowOfflineAccess = true,

    //I Don't want to do this
    Claims = new List<Claim>
    {   
        new Claim("type","value")
    }
}

I do not want the above because i do not want the the claim to be part of the client_claims in the database. I need to create it on the fly on token request. I hope my question is clearer now.

Answer

flexxxit picture flexxxit · May 12, 2017

With some inquiries I finally found out how to do this. I needed a way to add claims dynamically to the client when token was requested.

In order to do that I had to extend ICustomTokenRequestValidator and then include my class in Startup.cs thorough dependency injection

public class DefaultClientClaimsAdder : ICustomTokenRequestValidator
{
    public Task ValidateAsync(CustomTokenRequestValidationContext context)
    {
        context.Result.ValidatedRequest.Client.AlwaysSendClientClaims = true;
        context.Result.ValidatedRequest.ClientClaims.Add(new Claim("testtoken","testbody"))

        return Task.FromResult(0);
    }
}

Configure services in Startup.cs

 services.AddTransient<ICustomTokenRequestValidator, DefaultClientClaimsAdder>();