skip to Main Content

I have a .NET web server with JWT authentication that checks only the signing key. It’s used by other (internal) servers that need a fixed token that doesn’t expire.

In .NET 6 it worked fine. After upgrading to .NET 8 the requests always return 401 with the error "The signature key was not found".

My authentication config code:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer("external", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        RequireExpirationTime = false,
        ValidateLifetime = false,
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(customKey)),
    };
});

The JWT payload is minimal. It is signed with the customKey and looks something like this:

header:

{
  "alg": "HS256"
}

payload:

{
  "sub": "100",
  "name": "Another Server",
  "iat": 1626260955,
  "scopes": [
    "scope_1",
    "scope_2"
  ]
}

In the logs I get the following message:

Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7] external was not authenticated.
Failure message: IDX10517: Signature validation failed. The token's kid is missing. Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey, KeyId: '', InternalId: 'XzATZhHqoi5EL7v3Ol4N3Sbp9y2ZYmyC60I32Bos-0E'. , KeyId:  '.
Number of keys in TokenValidationParameters: '1'.

I can’t understand what changed in .NET 8 and how to make it work.

2

Answers


  1. Chosen as BEST ANSWER

    I eventually used an external package jose-jwt to perform the token authentication:

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer("external", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            RequireExpirationTime = false,
            ValidateLifetime = false,
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateIssuerSigningKey = false,
            SignatureValidator = (string token, TokenValidationParameters parameters) =>
            {
                // custom signature validation
                try
                {
                    string json = Jose.JWT.Decode(token, Encoding.ASCII.GetBytes(customKey));
                    return new JsonWebToken(token);
                }
                catch
                {
                    return null;
                }
            }
        };
    });
    

  2. switch from JwtSecurityToken and JwtTokenValidators to JsonWebToken and TokenHandler in .NET 8.

    you can set JwtBearerOptions.UseSecurityTokenValidators = true

    https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/8.0/securitytoken-events

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search