Sudden'没有为securityToken找到有效的密钥映射'错误

时间:2015-02-09 11:56:00

标签: azure model-view-controller

TL; DR

我们的网站突然出现以下错误,没有代码或web.config更改。 Azure会改变吗?

我有一个在Azure上运行的网站几个月没有任何问题。然后前几天,我们现在有这个错误:

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

我们未对web.configTenantsIssuingAuthorityKeys中的值进行任何更改。

搜索SO和网络会提供大量基于代码的答案,但我们还没有更改任何代码。

web.config是这样的:

<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>

issuerNameRegistry类如下:

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);
    }
}

2 个答案:

答案 0 :(得分:1)

this Technet文章来看,似乎微软可能已经更新了处理Tenant密钥的方式。

我必须将以下代码添加到我的Global.asax.cs文件中:

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

    // ....

    string configPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config";
    string metadataAddress =
                    ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
    ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath); 
}

答案 1 :(得分:1)

在类似的帖子上查看我的答案。它仅适用于在VS2013或更高版本中创建的解决方案。 https://stackoverflow.com/a/38131092/5919316

以下是它的副本:

对于在VS2013及更高版本中创建的解决方案,解决方案应包含自动滚动键的逻辑。无需将值放在web.config文件中。

将解决方案从本地迁移到其他环境时,可能会遇到此问题。在这种情况下,您可能会尝试将解决方案指向Azure Active Directory中的新应用程序。请检查以下内容:

  • 确保web.config中的所有网址都指向正确的网址,而不是在本地设置时自动生成的网址
  • 从IssuingAuthorityKeys表中删除所有企业。当您重新构建解决方案并运行它时,密钥将自动填充。在服务器上,您可能需要手动替换dll才能刷新
  • 最后也是最重要的,删除租户表中的所有行。在新环境中首次运行时,拥有Active Directory的管理员必须注册并授权该应用程序。

如果在这些步骤后仍未自动填充两个表中的值,请查看此article以了解有关如何手动获取值的步骤。