2013-10-07 161 views
0

我有一个在某些情况下使用ADFS身份验证的项目。配置是从数据库中读取的,URLs不同于客户,因此有很多配置选项,我不能在我的Web.config中进行硬编码。有时ADFS例外:ID1032“至少必须指定一个'audienceUri'...”

的问题是,我得到以下错误:

ID1032: At least one 'audienceUri' must be specified in the SamlSecurityTokenRequirement when the AudienceUriMode is set to 'Always' or 'BearerKeyOnly'

但我不明白这一点一如既往,我不能复制。这很烦人,因为只要我不能重现它,我就无法真正调试它。而且我不确定我是否做了一切正确的事情。也许一些ADFS专家可以看看它。

(我靠当事人及其相应的ADFS服务器之间的信任关系已经建立,当然)。

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

从我Web.config一些片段:

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

那些失败值在每次请求被覆盖(请参阅我的Login()方法如下图),但我有我的Web.config指定的东西,所以我至少选择指定一个有效的URI。由于我的服务使用DNS Round-Robin(共享相同的机器密钥)在多台机器上运行,因此必须更换默认的SessionSecurityTokenHandler

然后我有一个叫做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 
    } 

    // ... 
} 

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

回答

0

由于异常说,你需要的audienceUri,我会通过添加一个下

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

的audienceUri是URI ADFS返回到您的应用程序启动。您可以重写引擎以接受任意返回结果,这不会改变事实,即在配置中确实需要至少一个uri。

+0

一个好主意(我会尝试它),但为什么大多数情况下它会在没有配置的受众URI的情况下工作?此时,我仅通过代码设置了观众URI,仅在一段时间内只发生了这种异常。 – fero

+0

伟大的问题,听起来像authorizaiton过滤器有时不起作用?没有更深入的调试,我想不出一个明显的原因。 –

相关问题