【问题标题】:Sometimes ADFS exception: ID1032 "At least one 'audienceUri' must be specified..."有时 ADFS 异常:ID1032“必须指定至少一个 'audienceUri'...”
【发布时间】:2013-10-08 01:37:46
【问题描述】:

我有一个在某些情况下使用 ADFS 身份验证的项目。配置是从数据库中读取的,并且 URL 因客户而异,因此我无法在 Web.config 中硬编码许多配置选项。

问题是我收到以下错误:

ID1032:当 AudienceUriMode 设置为“Always”或“BearerKeyOnly”时,必须在 SamlSecurityTokenRequirement 中指定至少一个“audienceUri”

但我并不总是得到它,而且我无法重现它。这很烦人,因为只要我无法重现它,我就无法真正调试它。而且我不确定我做的一切是否正确。也许一些 ADFS 专家可以看看它。

(当然,我的依赖方与其相应的 ADFS 服务器之间的信任已经建立。)

这是我的代码(只是其中有趣的部分),请询问是否有任何遗漏或不清楚的地方。

Web.config的一些sn-ps:

<system.webServer>
  <modules>
    <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
    <add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
    <add name="ClaimsPrincipalHttpModule" type="Microsoft.IdentityModel.Web.ClaimsPrincipalHttpModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
    <!-- ... -->
  </modules>
  <!-- ... -->
</system.webServer>
<microsoft.identityModel>
  <service>
    <securityTokenHandlers>
      <remove type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler" />
      <add type="MyProject.MachineKeySessionSecurityTokenHandler" />
    </securityTokenHandlers>
    <federatedAuthentication>
      <wsFederation passiveRedirectEnabled="false"
                    issuer="https://fail/IssuerEndpoint"
                    realm="https://fail/FederationResult"
                    homeRealm="https://fail"
                    requireHttps="true" />
    </federatedAuthentication>
  </service>
</microsoft.identityModel>

那些 fail 值将被每个请求覆盖(请参阅下面我的 Login() 方法),但我必须在我的 Web.config 中指定一些内容,所以我选择至少指定一个有效的 URI .必须替换默认的SessionSecurityTokenHandler,因为我的服务在多台机器上运行,使用 DNS 循环(共享同一个机器密钥)。

然后我有一个名为AdfsTrustFilter 的类,它实现了IAuthorizationFilter。我知道这有点开销,但是由于项目结构,这个过滤器被用作每个请求的全局过滤器(顺序是整个项目中的最小值)。在OnAuthorization方法中,我完成配置如下:

public sealed class AdfsTrustFilter : IAuthorizationFilter
    public void OnAuthorization(AuthorizationContext filterContext)
        // ...

        var fam = FederatedAuthentication.WSFederationAuthenticationModule;

        fam.ServiceConfiguration = new ServiceConfiguration
        {
            AudienceRestriction = new AudienceRestriction(AudienceUriMode.Always),
            CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust,
            // MyIssuerNameRegistry checks whether a fingerprint is known and some other stuff
            IssuerNameRegistry = new MyIssuerNameRegistry()
        };

        // config.OwnPath contains something like "https://my.app.com/AppRoot/"
        fam.ServiceConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(config.OwnPath));
    }
}

这是启动身份验证的代码:

public ActionResult Login()
{
    // ...

    // again something like "https://my.app.com/AppRoot/"
    string baseUrl = Config.OwnPath.TrimEnd('/') + "/";

    // adfs endpoint for this customer: i.e. "https://identity.provider.net/adfs/ls/"
    string endpoint = Config.AdfsConfig.IdentityProvider.Endpoint;

    // the code behind FederationResult is shown below
    var signIn = new SignInRequestMessage(new Uri(endpoint), baseUrl + "/Adfs/FederationResult")
                        {
                            Context = baseUrl
                        };

    var url = signIn.WriteQueryString();

    return Redirect(url);
}

最后是FederationResult 回调:

public ActionResult FederationResult()
{
    WSFederationAuthenticationModule fam = FederatedAuthentication.WSFederationAuthenticationModule;
    HttpRequest request = System.Web.HttpContext.Current.Request;

    if (fam.CanReadSignInResponse(request, true))
    {
        var id = (IClaimsIdentity) User.Identity;

        // do something
    }

    // ...
}

P.S.:ADFS 服务器最近从 2008 R2 升级到 2012,但这并没有改变任何东西。 ADFS 版本始终为 2.0。

【问题讨论】:

    标签: c# asp.net-mvc wif adfs


    【解决方案1】:

    由于异常表明您需要 AudienceUri,我将首先在下面添加一个

     <microsoft.IdentityModel>
        <service>
           <audienceUris>
              <add value="https://yourdomain/theaudienceuri" />
    

    AudienceUri 是 adfs 返回到您的应用程序的 Uri。您可以覆盖引擎以接受任意返回结果,这不会改变您在配置中确实需要至少一个 uri 的事实。

    【讨论】:

    • 一个好主意(我会尝试一下),但为什么它在大多数时间没有配置的受众 URI 也能工作?这时候我只通过代码设置了观众 URI,偶尔会得到这个异常。
    • 好问题,听起来授权过滤器有时不起作用?如果没有更深入的调试,我想不出一个明显的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多