Skip to content

JWT Token configuration

Jon P Smith edited this page Apr 6, 2023 · 3 revisions

JSON Web Token (JWT) Bearer Token (shortened to 'JWT Token') are supported by ASP.NET Core and work well with WebAPI systems and Microservices. This page shows you how to set up a JWT Token that contains the AuthP's Permission, and optional multi-tenant DataKey claims, into a JWT Token. This page also contains information on how to set up AuthP's JWT Refresh Token to improve security.

NOTE: The AuthPermissions Example2 project is a ASP.NET WebAPI using JWT Token (and AuthP's JWT Refresh Token feature). You can try this application via its Swagger front-end. All the examples in this page are from that example.

Configuring a JWT Token in ASP.NET Core

I haven't found any good Microsoft documentation on setting up a JWT Token for authentication. The best article on setting up JWT Tokens in ASP.Net Core I found was by Rick Strahl and I followed that (but changes some things to match AuthP's approach to Roles/Permissions).

I recommend you read Rick Strahl article, but here is the ASP.NET Core setup from AuthPermissions Example2's Startup class, but some JWT Refresh Token setup removed.

Note the use of the JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear() to ensure the userId in the token matches the user's userId.

var jwtData = new JwtSetupData();
builder.Configuration.Bind("JwtData", jwtData);
//The solution to getting the nameidentifier claim to have the user's Id 
//was found in https://stackoverflow.com/a/70315108/1434764
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(auth =>
{
    auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    auth.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
    .AddJwtBearer(options =>
    {
        options.SaveToken = true;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = jwtData.Issuer,
            ValidateAudience = true,
            ValidAudience = jwtData.Audience,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtData.SigningKey)),
            ClockSkew = TimeSpan.Zero //The default is 5 minutes, but we want a quick expires for JTW refresh

        };

        //This code came from https://www.blinkingcaret.com/2018/05/30/refresh-tokens-in-asp-net-core-web-api/
        //It returns a useful header if the JWT Token has expired
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                {
                    context.Response.Headers.Add("Token-Expired", "true");
                }
                return Task.CompletedTask;
            }
        };
    });

And the appsetting.json file contains the following json setting. This contains the data needed for the JWT Token. It is in the appsetting so that these values can be overwritten when you deploy to production.

{
  "JwtData": {
    "Issuer": "https://localhost:44304",
    "Audience": "https://localhost:44304",
    "SigningKey": "some-long-secret-key-that-is-NOT-in-your-appsetting-file" 
  }
}

NOTE: The "SigingKey" is a important value that must be kept secret. When you are deploying to production you should either this value during deployment, or use user secrets.

Next steps

See Using JWT Tokens

Articles / Videos

Concepts

Setup

Usage

Admin

SupportCode

Clone this wiki locally