Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IDX10501: Signature validation failed. Unable to match keys

Please help me to understand the difference between JWT token validation from the ASP netcore application and the netcore Kestrel hosted application.

There are two applications that verifies token using the source code like below:

public static IServiceCollection AddJwtToken(this IServiceCollection services, OAuthConfig config)
{
    services.AddMvc();
    services.AddAuthorization();

    Logger.DebugFormat("AddJwtBearer authority:{0} audience:{1}", config.GetAuthority(), config.Resource);

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options => new JwtBearerOptions
        {
            Authority = config.GetAuthority(),
            Audience = config.Resource,
    });

    return services;
}

it is pretty simple and it works well if token is being validated from the asp net core 2.2 application

// in the asp.net core
var builder = WebHost.CreateDefaultBuilder(args);
builder
        .UseStartup<Startup>()
        .ConfigureKestrel(_ => _.ConfigureEndpoints())
        .UseSerilog();

And there is another application (console) that starts the same rest service host using the UseKestrel

//in the console app
var builder = WebHost.CreateDefaultBuilder()
    .UseNLog()
    .UseKestrel(_ => _.ConfigureEndpoints())
    .UseStartup<Startup>();

the only one significant difference is that there is UseKestrel in the console via ConfigureKestrel for asp.net core.

The same source code (and configuration) is used to get token from the Azure AD. Please find it as the gist here. It is configured to get token from the https://login.microsoftonline.com/{tenant}/v2.0 provider. The same token endpoint, clientid, secret and scope values are used for both cases.

The problem is that AddJwtBearer validates the token in the asp.net core and does not in the console app. the error is

Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match keys:
kid: 'BB8CeFVqyaGrGNuehJIiL4dfjzw',
token: '{"typ":"JWT","alg":"RS256","kid":"BB8CeFVqyaGrGNuehJIiL4dfjzw"}.{"aud":"2c163c99-935b-4362-ae0d-657f589f5565","iss":"https://login.microsoftonline.com/{tenantidhere}/v2.0

Why asp.net core host validates the token (for the first AddJwtBearer implementation) and console host fails?

Thank you

like image 276
oleksa Avatar asked Nov 14 '19 12:11

oleksa


2 Answers

to solve this error I've to load keys from the openid provider as below:

Logger.DebugFormat("AddJwtBearer authority:{0} audience:{1}", config.GetAuthority(), config.Resource);

IList<string> validissuers = new List<string>()
{
    config.GetAuthority(),
};

var configManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{validissuers.Last()}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());

var openidconfig = configManager.GetConfigurationAsync().Result;

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, _ =>
    {
        _.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
        {
            ValidateAudience = true,
            ValidAudience = config.Resource,

            ValidateIssuer = true,
            ValidIssuers = new[] { config.GetAuthority() },

            ValidateIssuerSigningKey = true,
            IssuerSigningKeys = openidconfig.SigningKeys,

            RequireExpirationTime = true,
            ValidateLifetime = true,
            RequireSignedTokens = true,
        };

        _.RequireHttpsMetadata = false;

    });

And it started to work for both cases. But what is the difference with the old AddJwtBearer implementation and the new one (related to the keys validation)? Keys where downloaded and supplied using the IssuerSigningKeys = openidconfig.SigningKeys but why it is not loaded automatically using the .well-known/openid-configuration by the AddJwtBearer middleware ?

like image 148
oleksa Avatar answered Oct 18 '22 23:10

oleksa


In my case, the same error was because of inadvertent use of the token received from one environment (https://dev/identity) and validated in another environment (i.e. http://local/identity).

like image 34
Baglay Vyacheslav Avatar answered Oct 18 '22 21:10

Baglay Vyacheslav