{"id":5545,"date":"2019-05-13T04:58:29","date_gmt":"2019-05-13T04:58:29","guid":{"rendered":"https:\/\/blogs.aaddevsup.xyz\/?p=5545"},"modified":"2022-05-04T15:34:59","modified_gmt":"2022-05-04T15:34:59","slug":"understanding-azure-ad-token-signing-certificate-kid","status":"publish","type":"post","link":"https:\/\/blogs.aaddevsup.xyz\/2019\/05\/understanding-azure-ad-token-signing-certificate-kid\/","title":{"rendered":"Understanding Azure AD token signing certificate (kid)"},"content":{"rendered":"

Introduction<\/h1>\n

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<\/a> 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:<\/p>\n

IDX10501: Signature validation failed. Unable to match ‘kid’ or IDX10501: Signature validation failed. Unable to match key<\/strong><\/span><\/p>\n

The setup:<\/h1>\n

To demonstrate the concept, I have registered the following 3 Applications in Azure AD:<\/p>\n

bhfrontend app<\/strong> – used to sign in and get an access token to one of the following backend app:
bhbackend app<\/strong> – backend oauth2 application which the bhfrontend app requests an access token for
SharepointSAMLTest app<\/strong> – backend SAML application which the bhfrontend app requests an access token for<\/p>\n

    \n
  1. bhbackend \u2013 OAuth2 app (created from Azure Active Directory -> App Registration -> New Registration in the Azure portal).<\/li>\n<\/ol>\n

    \"\"<\/p>\n

      \n
    1. SharepointSAMLTest \u2013 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.<\/li>\n<\/ol>\n

      \"\"<\/p>\n

        \n
      1. bhfrontend \u2013 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.<\/li>\n<\/ol>\n

        \"\"<\/p>\n

        OAuth2 resource application<\/h1>\n

        Use Postman’s Authorization Code<\/a> 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 <\/strong><\/span><\/p>\n

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

        Note<\/strong><\/span>: The application demonstrated here is a V1 app. For V2 app, use https:\/\/login.microsoftonline.com\/common\/discovery\/v2.0\/keys<\/a> instead of.<\/p>\n

        \"\"<\/p>\n

        SAML Resource Application<\/h1>\n

        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.<\/p>\n

        https:\/\/login.microsoftonline.com\/<\/span><tenant name><\/span>\/discovery\/keys?appid=<\/span><SAML App ID><\/span><\/strong><\/span>
        <\/span><\/p>\n

        \"\"<\/p>\n

        The above keys discovery endpoint can be obtained from the app-specific metadata endpoint:<\/p>\n

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

        This is also documented below for both V1 and V2 endpoint:<\/p>\n

        V2 OpenID Connect protocol<\/a>
        V1 OpenID Connect protocol<\/a><\/p>\n

        \n

        If your app has custom signing keys as a result of using the claims-mapping<\/a> feature, you must append an appid<\/code> query parameter containing the app ID in order to get a jwks_uri<\/code> 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<\/code> contains a jwks_uri<\/code> of https:\/\/login.microsoftonline.com\/{tenant}\/discovery\/v2.0\/keys?appid=6731de76-14a6-49ae-97bc-6eba6914391e<\/code>.<\/p>\n

        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.<\/p>\n<\/blockquote>\n

        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.<\/p>\n

        OpenID Connect middleware:<\/strong>
        use 
        OpenIdConnectAuthenticationOptions.MetadataAddress Property<\/a><\/p>\n

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

        Microsoft.Identity.Web Web App Authentication:<\/strong><\/p>\n

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

        Microsoft.Identity.Web Web API Authentication:<\/strong><\/p>\n

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

        Conclusion<\/h1>\n

        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<\/a> article.<\/p>\n\n\n

        <\/p>\n","protected":false},"excerpt":{"rendered":"

        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…<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[24,150,84,96],"class_list":["post-5545","post","type-post","status-publish","format-standard","hentry","category-azure-ad","tag-access-token","tag-certficate","tag-how-to","tag-keys"],"_links":{"self":[{"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/posts\/5545"}],"collection":[{"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/comments?post=5545"}],"version-history":[{"count":39,"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/posts\/5545\/revisions"}],"predecessor-version":[{"id":8816,"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/posts\/5545\/revisions\/8816"}],"wp:attachment":[{"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/media?parent=5545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/categories?post=5545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.aaddevsup.xyz\/wp-json\/wp\/v2\/tags?post=5545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}

        JWT Bearer Authentication middleware:<\/strong>
        use 
        JwtBearerOptions.MetadataAddress<\/a> Property<\/p>\n