Version 5.x has been out of support since December 13, 2022, and this corresponding section of the documentation is no longer maintained. We strongly recommend upgrading to a supported version.

Using JWTs

On ASP.NET Core, you typically use the JWT authentication handler for validating JWT bearer tokens.

Validating a JWT token

First you need add a reference to the authentication handler to your API project:

<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />

If all you care about, is making sure that an access token comes from your trusted IdentityServer, the following snippet shows the typical JWT validation configuration for ASP.NET Core:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                // base-address of your identityserver
                options.Authority = "https://demo.duendesoftware.com";

                // audience is optional, make sure you read the following paragraphs
                // to understand your options
                options.TokenValidationParameters.ValidateAudience = false;

                // it's recommended to check the type header to avoid "JWT confusion" attacks
                options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
            });
    }
}

On .NET Core 3.1 you need to manually reference the System.IdentityModel.Tokens.Jwt Nuget package version 5.6 to be able to check the type header.

Adding audience validation

Simply making sure that the token is coming from a trusted issuer is not good enough for most cases. In more complex systems, you will have multiple resources and multiple clients. Not every client might be authorized to access every resource.

In OAuth there are two complementary mechanisms to embed more information about the “functionality” that the token is for - audience and scope (see defining resources for more information).

If you designed your APIs around the concept of API resources, your IdentityServer will emit the aud claim by default (api1 in this example):

{
    "typ": "at+jwt",
    "kid": "123"
}.
{
    "aud": "api1",

    "client_id": "mobile_app",
    "sub": "123",
    "scope": "read write delete"
}

If you want to express in your API, that only access tokens for the api1 audience (aka API resource name) are accepted, change the above code snippet to:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.Authority = "https://demo.duendesoftware.com";
                options.Audience = "api1";

                options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
            });
    }
}