AzureAD / azure-activedirectory-identitymodel-extensions-for-dotnet

IdentityModel extensions for .Net
MIT License
1.06k stars 400 forks source link

IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey #1334

Closed EkwofiePrax closed 4 years ago

EkwofiePrax commented 4 years ago

@brentschmaltz I'm being faced with similar issue that's been reported in here. I have tried all the suggestions but I'm getting no where.

Am I missing something?

I have added a snapshot of my code

IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey

I'm using MSAL interceptor in Angular 8 code to send access token to the server "C# .NET core 3.1".

//***** public static JwtSecurityToken Validate(string token) {

    string stsDiscoveryEndpoint = "https://login.microsoftonline.com/eddf9e42-9a7f-4639-8042-***********/.well-known/openid-configuration?appid=7391aebb-1a35-4ad7-8166-xxxxxxxxxx"; // https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";

    ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
    OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;

    TokenValidationParameters validationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidIssuer = config.Issuer,
        IssuerSigningKeys = config.SigningKeys,
        ValidateIssuerSigningKey = false,
        ValidateIssuer = true,
        ValidateActor = false,
        ValidateLifetime = true
    };

    IdentityModelEventSource.ShowPII = true;
    JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();

    SecurityToken jwt;
    var result = tokendHandler.ValidateToken(token, validationParameters, out jwt);
    return jwt as JwtSecurityToken;
}

/* IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey, KeyId: 'HlC0R12skxNZ1WQwmjOF_6t_tDE', InternalId: '91ea3222-c9ea-4aa4-a515-83f2b195f989'. , KeyId: HlC0R12skxNZ1WQwmjOF_6t_tDE '. kid: 'HlC0R12skxNZ1WQwmjOF_6t_tDE'. Exceptions caught: ''. token: '{"alg":"RS256","typ":"JWT","nonce":"19yszC4xPiqhnbI587HT_08QFjftE7J3qE8F9xw_sqY","x5t":"HlC0R12skxNZ1WQwmjOF_6t_tDE","kid":"HlC0R12skxNZ1WQwmjOF_6t_tDE"}.{"aud":"00000003-0000-0000-c000-000000000000","iss":"https://sts.windows.net/eddf9e42-9a7f-4639-8042-110281cf41a2/","iat":1581413726,"nbf":1581413726,"exp":1581417626,"acct":0,"acr":"1","aio":"42NgYLgWut8sY6dad5urN6/nxuP8P7Z6ZXr1Wwl355xibZu8nxMA","amr":["pwd"],"app_displayname":"SoraxWeb","appid":"7391aebb-1a35-4ad7-8166-xxxxxxxx","appidacr":"0","family_name":"kwofie","given_name":"Ernest","ipaddr":"212.161.81.38","name":"Exxxx kxxxx","oid":"9f9efce3-37e5-4018-8035-7ffc6323e827","onprem_sid":"S-1-5-21-3789744388-407605227-1228871550-7770","platf":"3","puid":"100320003319DDA9","scp":"Mail.Send openid profile User.Read User.ReadWrite email","sub":"LhkC5zL_zJm-MZBjJDYCz5Asjm7Nwg9tHUehKVSH40A","tid":"eddf9e42-9a7f-4639-8042-*****","unique_name":"Exxxx.kxxxx@xxxx.com","upn":"Exxxx.kxxxx@xxxxx.com","uti":"3RsEnJpEokmZb-Y3MwJzAA","ver":"1.0","xms_st":{"sub":"zSJz0JM6iB6SRwxi1ZZm_1F__aYqHhEDtjb5qkege_o"},"xms_tcdt":1443089411}'. */

Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddCors(options => options.AddPolicy(MyAllowSpecificOrigins, builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); })); services.AddControllers(); }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();
    app.UseCors(MyAllowSpecificOrigins);
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}
GeoK commented 4 years ago

@EkwofiePrax - Why are you trying to validate an access token for Graph? This token requires special processing in order to validate.

Please refer to: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-524434987

More on 'special processing': https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-405683736

EkwofiePrax commented 4 years ago

Hi @GeoK thanks for your direction, much appreciate, I guess the cue was in the "aud":"00000003-0000-0000-c000-000000000000" https://www.shawntabrizi.com/aad/common-microsoft-resources-azure-active-directory/ image

Looking at protectedResourceMap below: I was using graph.microsoft.com scope for my API as follows : ["user.read", "mail.send"]]. image

This was causing the validation to fail with error: Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: 'IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey, KeyId: 'HlC0R12skxNZ1WQwmjOF_6t_tDE', InternalId:

image

I had to go Azure and preform the following task: scope name : Read.All

image

in my Angular app, I had to update my protectedResourseMap to this: image

@GeoK I hope I havent missed anything here :)

GeoK commented 4 years ago

You shouldn't validate an access token for Graph. Still not sure why would you do that. Please review the comments linked in my previous comment.

In a nutshell, the signature is over the transformed nonce, so if you try and validate it directly, the signature will fail.

apasvistelik commented 1 year ago

For anyone facing this issue: I send the id_token instead of the access_token and now everything is fine.

brentschmaltz commented 1 year ago

@apasvistelik who are you sending the id_token to? id_tokens are not meant to be shared between applications.

apasvistelik commented 1 year ago

In my case, there is a combination of React frontend with NextJS server and .NET backend for the API. On the frontend, we use next-auth package with the AzureADProvider ('next-auth/providers/azure-ad') to receive the token. Then we add the id_token to the Bearer Authorization header and send requests to our API .NET backend.

markjsc commented 2 months ago

For anyone facing this issue: I send the id_token instead of the access_token and now everything is fine.

Late to the party, but this was the solution to the problem on my side.

In the AuthJs jwt() callback, I was capturing the Account's Access Token. It decoded as a valid JWT with what I thought were the correct attributes. But switching to the account.id_token was the right solution - the values were actually what was needed by the API.

//Next-JS auth.ts
callbacks: {
  //...
async jwt({ token, account, profile }) {
      if (account) {
        //IMPORTANT: Use the Account's ID Token here, NOT the AccessToken
        token.accessToken = account.id_token,
        token.id = profile?.id || account.userId
      }
      return token;
    }
}

//ASP.NET Core Program.cs
builder.Services
  .AddAuthentication()
  .AddJwtBearer("MicrosoftEntraId", configureOptions =>
{
    configureOptions.Authority = "https://login.microsoftonline.com/<YOUR_TENANT_ID>/v2.0; //the "iss" value from the token
    configureOptions.Audience = "<YOUR_APPLICATION/CLIENT_ID>"; //the "aud" value form the token
});