Introduction

Upon successful authentication, Azure AD issues a signed JWT token (id token or access token). The resource application needs to know the public key of the certificate used sign the token in order to validate the token signature. Depending upon the type (OAuth2 or SAML Application) of the resource application, the steps to obtain the pubic key information are different. An OWIN asp.net application can throw the following error when it’s not able to find the kid to validate the token signature:

IDX10501: Signature validation failed. Unable to match ‘kid’ or IDX10501: Signature validation failed. Unable to match key

The setup:

To demonstrate the concept, I have registered the following 3 Applications in Azure AD:

bhfrontend app – used to sign in and get an access token to one of the following backend app:
bhbackend app – backend oauth2 application which the bhfrontend app requests an access token for
SharepointSAMLTest app – backend SAML application which the bhfrontend app requests an access token for

  1. bhbackend – OAuth2 app (created from Azure Active Directory -> App Registration -> New Registration in the Azure portal).

  1. SharepointSAMLTest – SAML application (created from Azure AD -> Enterprise Application -> New Application -> Non-gallery application -> configure SAML Single sign-on). Note that Azure AD automatically assigns certificate to this application. This certificate is used to sign both a SAML token and an oauth2 token.

  1. bhfrontend – OAuth2 web app (created the same way as bhbackend above). In the API permissions add both bhbackend and SharepointSAMLTest app and grant admin consent. You will also need to create a password secret for this application (to be used later in an authorization code flow to get an access token). This application is used for sign in and get an access token for both the bhbackend app and the SharepointSAMLTest app.

OAuth2 resource application

Use Postman’s Authorization Code flow to obtain an access token for the bhbackend app. For oauth2 applications, use the following keys discovery endpoint to find the public key of the signing certificate: https://login.microsoftonline.com/common/discovery/keys 

I am using https://jwt.ms to decode the access token and kid in the access token should match one of the 3 kids at the end point.

Note: The application demonstrated here is a V1 app. For V2 app, use https://login.microsoftonline.com/common/discovery/v2.0/keys instead of.

SAML Resource Application

Again, use Postman to get an access token for the SharepointSAMLTest App. Azure AD uses the certificate created for this application to sign the token. For this scenario, we have to use the following keys discovery endpoint to get to the public key of that certificate. The App ID below can be found in the Properties section of that Enterprise App.

https://login.microsoftonline.com/<tenant name>/discovery/keys?appid=<SAML App ID>

The above keys discovery endpoint can be obtained from the app-specific metadata endpoint:

https://login.microsoftonline.com/<tenant name>/.well-known/openid-configuration?appid=<SAML App ID>

This is also documented below for both V1 and V2 endpoint:

V2 OpenID Connect protocol
V1 OpenID Connect protocol

If your app has custom signing keys as a result of using the claims-mapping feature, you must append an appid query parameter containing the app ID in order to get a jwks_uri pointing to your app’s signing key information. For example: https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration?appid=6731de76-14a6-49ae-97bc-6eba6914391e contains a jwks_uri of https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys?appid=6731de76-14a6-49ae-97bc-6eba6914391e.

Typically, you would use this metadata document to configure an OpenID Connect library or SDK; the library would use the metadata to do its work. However, if you’re not using a pre-built OpenID Connect library, you can follow the steps in the remainder of this article to do sign-in in a web app by using the Microsoft identity platform endpoint.

In the example above I use the bhfrontend application as OAuth2 application for sign in.  If this application is a SAML Application with Single Sign-On feature enabled, the same Signature Validation error can occur here.  To resolve the error one should use the application-specific metadata endpoint.  See below examples for both the OpenID Connect OWIN middleware of JWT Bearer Authentication middleware usage of the MetadataAddress property.

OpenID Connect middleware:
use OpenIdConnectAuthenticationOptions.MetadataAddress Property

app.UseOpenIdConnectAuthentication(
    new OpenIdConnectAuthenticationOptions
    {
        // Sets the ClientId, authority, RedirectUri as obtained from        web.config
        ClientId = clientId,
        Authority = authority,
        RedirectUri = redirectUri,
        MetadataAddress = "https://login.microsoftonline.com/<tenant name>/.well-known/openid-configuration?appid=<SAML App ID>"
        PostLogoutRedirectUri = redirectUri,
    }

JWT Bearer Authentication middleware:
use JwtBearerOptions.MetadataAddress Property

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    Audience = "...",
    Authority = "...",
    MetadataAddress = "https://login.microsoftonline.com/<tenant name>/.well-known/openid-configuration?appid=<SAML App ID>",
    TokenValidationParameters = new TokenValidationParameters
    {
       ...
    }
});

Microsoft.Identity.Web Web App Authentication:

services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
     .EnableTokenAcquisitionToCallDownstreamApi()
     .AddInMemoryTokenCaches();
services.Configure<MicrosoftIdentityOptions>(options => { options.MetadataAddress = "https://login.microsoftonline.com/<tenant name>/.well-known/openid-configuration?appid=<SAML App ID>"; });

Microsoft.Identity.Web Web API Authentication:

using Microsoft.AspNetCore.Authentication.JwtBearer;
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme,options => { options.MetadataAddress = "https://login.microsoftonline.com/<tenant name>/.well-known/openid-configuration?appid=<SAML App ID>"; });

Conclusion

I hope this blog post provides clarification on how to get to the public key of the signing certificate to validate the token signature. Please leave us a comment if you find this helpful. If you want to learn more about Azure AD signing keys rollover, you should take a look at this article.

2 Thoughts to “Understanding Azure AD token signing certificate (kid)”

  1. Ashish Patil

    Excellent article that clearly explains (with screenshots) how to get the public key. Reading your article assisted me in coding the verification of the signature of the id token. Public key as you explained is the most important part of verifying the signature.

    1. Bac Hoang [MSFT]

      Glad it helped.

Leave a Comment