Looking for ASP.NET Core w/ Clerk JWTs? See below.
Clerk.Net
: Provides the standalone API Client as a Kiota-generated wrapper over Clerk's OpenAPI spec. Compatible with .NET 6+ and .NET Framework 4.7.2+.
Clerk.Net.DependencyInjection
: Extensions to register the ClerkApiClient
into your DI container. Compatible with .NET 6+.
These libraries are configured as native AoT compatible for .NET 8+ consumers.
Make sure to add your SecretKey
to your application configuration, ideally via the dotnet secrets manager.
- Install
Clerk.Net.DependencyInjection
from Nuget. - Add the following code to your service configuration:
builder.Services.AddClerkApiClient(config =>
{
config.SecretKey = builder.Configuration["Clerk:SecretKey"]!
});
- Request the
ClerkApiClient
in your services
public class MyBackgroundWorker : BackgroundService
{
private readonly ClerkApiClient _clerkApiClient;
public MyBackgroundWorker(ClerkApiClient clerkApiClient)
{
_clerkApiClient = clerkApiClient;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var invites = await _clerkApiClient.Organizations["org_abc1234"].Invitations.GetAsync(x =>
{
x.QueryParameters.Status = "pending";
});
}
}
If you want to use the client by itself, install Clerk.Net
and call ClerkApiClientFactory.Create
, passing in your secret key.
The returned client should be treated as a singleton and created once for the lifetime of your application.
If you need to configure the underlying HttpClient
used by the client, you can do in one of two ways:
- Configure the
IHttpClientBuilder
returned byAddClerkApiClient
. - Pass in a custom
HttpClient
instance toClerkApiClientFactory.Create
For unit testing, see Unit testing Kiota API clients.
You might have stumbled upon this repo looking for a solution for validating Clerk JWTs, so I'll include the answer here for completion. Configuring JWT auth for Clerk is a tad unusual as they want you to validate the azp
parameter instead of specifying an audience
.
This claim isn't normally validated at the authentication layer, and so you'll need some extra code to get things working:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(x =>
{
// Authority is the URL of your clerk instance
x.Authority = builder.Configuration["Clerk:Authority"];
x.TokenValidationParameters = new TokenValidationParameters()
{
// Disable audience validation as we aren't using it
ValidateAudience = false,
NameClaimType = ClaimTypes.NameIdentifier
};
x.Events = new JwtBearerEvents()
{
// Additional validation for AZP claim
OnTokenValidated = context =>
{
var azp = context.Principal?.FindFirstValue("azp");
// AuthorizedParty is the base URL of your frontend.
if (string.IsNullOrEmpty(azp) || !azp.Equals(builder.Configuration["Clerk:AuthorizedParty"]))
context.Fail("AZP Claim is invalid or missing");
return Task.CompletedTask;
}
};
});
Your frontend should call Clerk-JS's getToken
as part of its HTTP middleware and append the token (prefixed with Bearer
) to the Authorization
header, for example:
async onRequestInit({ requestInit }) {
requestInit.headers = {
...requestInit.headers,
Authorization: `Bearer ${await getToken()}`
}
}
I am not affiliated with nor represent Clerk. All support queries regarding the underlying service should go to Clerk Support.