Customer has an ASP.Net MVC application using both WS-Federation OWIN middleware and Windows Identity Foundation (WIF) to authenticate to Azure AD. The application works fine initially and then fails with the following error:

Error Details:
Server Error in ‘/’ Application.
WIF10201: No valid key mapping found for securityToken: ‘System.IdentityModel.Tokens.X509SecurityToken’ and issuer: ‘https://sts.windows.net/<Directory ID>/’.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.IdentityModel.Tokens.SecurityTokenValidationException: WIF10201: No valid key mapping found for securityToken: ‘System.IdentityModel.Tokens.X509SecurityToken’ and issuer: ‘https://sts.windows.net/<Directory ID>/’.

Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:
[SecurityTokenValidationException: WIF10201: No valid key mapping found for securityToken: ‘System.IdentityModel.Tokens.X509SecurityToken’ and issuer: ‘https://sts.windows.net/<Directory ID>/’.]
System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ValidateToken(SecurityToken token) +873
System.IdentityModel.Tokens.SecurityTokenHandlerCollection.ValidateToken(SecurityToken token) +73
System.IdentityModel.Services.TokenReceiver.AuthenticateToken(SecurityToken token, Boolean ensureBearerToken, String endpointUri) +110
System.IdentityModel.Services.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequestBase request) +527
System.IdentityModel.Services.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args) +381
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +141
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +48
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +71
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.3535.0

Root Cause:

Windows Identity Foundation uses the certificate thumbprint(s) in the web.config file (shown below) to verify the signature of the token returned from Azure AD upon successful sign in.

  <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, 
    System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
    <authority name="https://sts.windows.net/<Directory ID>/">
      <keys>
        <add thumbprint="C142E..." />
        <add thumbprint="8BA94..." />
        <add thumbprint="D92E1..." />
      </keys>
      <validIssuers>
        <add name="https://sts.windows.net/<Directory ID>/" />
      </validIssuers>
    </authority>
  </issuerNameRegistry>

Note: The certificate thumbprints above can be generated from either the discovery keys endpoint ( https://login.microsoftonline.com/<Directory ID>/discovery/keys) or the federationmetadata endpoint ( https://login.microsoftonline.com/<Directory ID>/federationmetadata/2007-06/federationmetadata.xml)

The above error occurs when none of these certificate thumbprints match the one used by Azure AD to sign the token. Because Azure AD implements a signing key rollover mechanism for security purpose, the certificate used to sign the token changes over time. This key rollover causes the initial certificate thumbprints configured in the web.config file to become invalid, hence leading to the error.

Resolution:

You can either update the certificate thumbprints in the web.config file manually or use the programmatic approach documented in Vittorio Bertocci’s blog https://www.cloudidentity.com/blog/2013/04/02/auto-update-of-the-signing-keys-via-metadata/

using System;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System.Configuration;
using System.IdentityModel.Tokens;

namespace MvcNewVINR
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void RefreshValidationSettings()
        {
            string configPath = 
              AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config";
            string metadataAddress = 
              ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
            ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);
        }
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            RefreshValidationSettings();
        }
    }
}

Note: The ‘ida:FederationMetadataLocation’ application setting above is the URL https://login.microsoftonline.com/<Directory ID>/federationmetadata/2007-06/federationmetadata.xml

The above certificate thumbprint update code runs when the Application is restarted or when its Application Pool gets recycled. For more information on Application Pool recycling refer to https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/recycling/.

If the application runs into an Access Denied error writing to the web.config file, see https://blogs.msdn.microsoft.com/cie/2016/01/15/error-access-to-the-path-esitesroot0web-config-is-denied-when-storing-azure-ads-public-key-in-web-config-of-an-azure-cloud-services-application/ for how to resolve the issue.

References:

Leave a Comment