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.
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>();
Alternatively, you can use ClientStore
to add new claims into clients.
public class YourClientStore : IClientStore
{
private readonly DbContext _context;
private readonly IMapper _mapper;
public YourClientStore(DbContext context,
IMapper mapper)
{
_context= context;
_mapper = mapper;
}
public Task<Client> FindClientByIdAsync(string clientId)
{
var dbClient = _context.Clients.AsQueryable()
.Where(x => x.ClientId == clientId)
.FirstOrDefault();
var client = _mapper.Map<Client>(dbClient);
if (client != null)
{
client.Claims.Add(new Claim("<your claim name>", "<your claim value>"));
}
return Task.FromResult(client);
}
}
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