0

TL;DR

Our website suddenly had the below error with no code or web.config changes. Would Azure have changed?

I have a website which has been running on Azure with no issues for a few months. Then the other day, we now have this error:

WIF10201: No valid key mapping found for securityToken: 'System.IdentityModel.Tokens.X509SecurityToken' and issuer: 'https://sts.windows.net/<guid>/'.

We have made no changes to the web.config or the values in Tenants and IssuingAuthorityKeys.

Searching SO and the web give lots of code based answers, but we haven't changed any code.

The web.config is like this:

<system.identityModel>
  <identityConfiguration>
    <issuerNameRegistry type="DatabaseIssuerNameRegistry, Site.Web" />
    <audienceUris>
      <add value="https://localhost:44301" />
      <add value="https://<other urls...>" />
    </audienceUris>
    <securityTokenHandlers>
      <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </securityTokenHandlers>
    <certificateValidation certificateValidationMode="None" />
  </identityConfiguration>
</system.identityModel>

The issuerNameRegistry class is as follows:

public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
    public static bool ContainsTenant(string tenantId)
    {
        using (DBEntities context = new DBEntities())
        {
            return context.Tenants
                .Where(tenant => tenant.Id == tenantId)
                .Any();
        }
    }

    public static bool ContainsKey(string thumbprint)
    {
        using (DBEntities context = new DBEntities())
        {
            return context.IssuingAuthorityKeys
                .Where(key => key.Id == thumbprint)
                .Any();
        }
    }

    public static void RefreshKeys(string metadataLocation)
    {
        IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);

        bool newKeys = false;
        bool refreshTenant = false;
        foreach (string thumbprint in issuingAuthority.Thumbprints)
        {
            if (!ContainsKey(thumbprint))
            {
                newKeys = true;
                refreshTenant = true;
                break;
            }
        }

        foreach (string issuer in issuingAuthority.Issuers)
        {
            if (!ContainsTenant(GetIssuerId(issuer)))
            {
                refreshTenant = true;
                break;
            }
        }

        if (newKeys || refreshTenant)
        {
            using (DBEntities context = new DBEntities())
            {
                if (newKeys)
                {
                  context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
                  foreach (string thumbprint in issuingAuthority.Thumbprints)
                  {
                      context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
                  }
                }

                if (refreshTenant)
                {
                    foreach (string issuer in issuingAuthority.Issuers)
                    {
                        string issuerId = GetIssuerId(issuer);
                        if (!ContainsTenant(issuerId))
                        {
                            context.Tenants.Add(new Tenant { Id = issuerId });
                        }
                    }
                }
                context.SaveChanges();
            }
        }
    }

    private static string GetIssuerId(string issuer)
    {
        return issuer.TrimEnd('/').Split('/').Last();
    }

    protected override bool IsThumbprintValid(string thumbprint, string issuer)
    {
        return ContainsTenant(GetIssuerId(issuer))
            && ContainsKey(thumbprint);
    }
}
rhughes
  • 9,257
  • 11
  • 59
  • 87

2 Answers2

1

Judging from this Technet article, it seems that Microsoft may have updated the way they handle Tenant keys.

I had to add the following code into my Global.asax.cs file:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    // ....

    string configPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config";
    string metadataAddress =
                    ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
    ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath); 
}
rhughes
  • 9,257
  • 11
  • 59
  • 87
1

Check out my answer on a similar post. It only applies to solutions created in VS2013 or later. https://stackoverflow.com/a/38131092/5919316

Here is a copy of it:

For solutions created in VS2013 and later, the solution should contain the logic to roll over keys automatically. No need to put the value in the web.config file.

You might run into this issue when migrating your solution from local to another environment. In that case you will probably try to point your solution to a new application in Azure Active Directory. Check the following:

  • Make sure all urls in the web.config are pointing to the correct url not the one automatically generated when you set it up locally
  • Remove all enteries from IssuingAuthorityKeys table. The keys will autopopulate when you re-build the solution and run it. On the server you might need to replace the dlls manually for it to refresh
  • Last and most important, delete all rows from the Tenants table. On the first run on the new environment, an Admin from the owning Active Directory has to sign up and authorize the application.

If the values in both tables are still not populated automatically after these steps, check this article for steps on how to manually get the values.


Community
  • 1
  • 1
Ahmed Mansour
  • 527
  • 5
  • 13