Skip to content
We just launched Duende IdentityServer v7.2.0 and BFF v3.0. Check it out!

Client Assertions

If your token client is using a client assertion instead of a shared secret, you can provide the assertion in two ways

  • use the request parameter mechanism to pass a client assertion to the management
  • implement the IClientAssertionService interface to centralize client assertion creation

Here’s a sample client assertion service using the Microsoft JWT library:

ClientAssertionService.cs
using Duende.AccessTokenManagement;
using Duende.IdentityModel;
using Duende.IdentityModel.Client;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
public class ClientAssertionService(IOptionsSnapshot<ClientCredentialsClient> options)
: IClientAssertionService
{
public Task<ClientAssertion?> GetClientAssertionAsync(
string? clientName = null, TokenRequestParameters? parameters = null)
{
if (clientName == "invoice")
{
var options1 = options.Get(clientName);
var descriptor = new SecurityTokenDescriptor
{
Issuer = options1.ClientId,
Audience = options1.TokenEndpoint,
Expires = DateTime.UtcNow.AddMinutes(1),
SigningCredentials = GetSigningCredential(),
Claims = new Dictionary<string, object>
{
{ JwtClaimTypes.JwtId, Guid.NewGuid().ToString() },
{ JwtClaimTypes.Subject, options1.ClientId! },
{ JwtClaimTypes.IssuedAt, DateTime.UtcNow.ToEpochTime() }
},
AdditionalHeaderClaims = new Dictionary<string, object>
{
{ JwtClaimTypes.TokenType, "client-authentication+jwt" }
}
};
var handler = new JsonWebTokenHandler();
var jwt = handler.CreateToken(descriptor);
return Task.FromResult<ClientAssertion?>(new ClientAssertion
{
Type = OidcConstants.ClientAssertionTypes.JwtBearer,
Value = jwt
});
}
return Task.FromResult<ClientAssertion?>(null);
}
private SigningCredentials GetSigningCredential()
{
throw new NotImplementedException();
}
}