我有一个在某些情况下使用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。
一个好主意(我会尝试它),但为什么大多数情况下它会在没有配置的受众URI的情况下工作?此时,我仅通过代码设置了观众URI,仅在一段时间内只发生了这种异常。 – fero
伟大的问题,听起来像authorizaiton过滤器有时不起作用?没有更深入的调试,我想不出一个明显的原因。 –