MVC 5、WIF (System.IdentityModel) 和 ADFS 未实际进行身份验证,联合注销时出错

Posted

技术标签:

【中文标题】MVC 5、WIF (System.IdentityModel) 和 ADFS 未实际进行身份验证,联合注销时出错【英文标题】:MVC 5, WIF (System.IdentityModel) & ADFS not actually authenticating, errors on federated signout 【发布时间】:2014-09-17 12:32:09 【问题描述】:

我正在努力在 Visual Studio 2013 中创建一个基于声明的 MVC 站点。

到目前为止我学到的一些东西:

System.Identity 已加入,Microsoft.Identity 已退出 许多教程(包括 Microsoft 的 4.5 指南)都已过时。例如,我认为不需要对项目模板生成的 .config 文件进行任何更改来添加模块/处理程序或任何东西。 Visual Studio 2013 中没有 Microsoft 内置/加载项 STS,就像 2012 年一样 Thinktecture 的 EmbeddedSTS 插件经常被推荐并且听起来很酷,但是 *://EmbeddedSTS/ 不能解决(??我不明白)。此外,其 IdentityServer v2- 的二进制链接目前已损坏(?) ADFS 功能需要 Windows Server 2012、域和自签名证书 - 如果您以前做过,这并不难,但如果您没有做过,学习曲线会很陡。 ADFS 需要 SSL - Visual Studio 2013/IIS Express 8 轻松支持 SSL 站点,只需确保端口号在:44300-44398 范围内 ADFS 管理器依赖方界面建议引用“sts”和“adfs/ls”的示例以及我认为具有误导性的内容。真的,他们应该只指向您的应用程序(例如https://localhost:44300)。虽然我的还不能正常工作,所以这可能与我的错误有关。 创建新的 Visual Studio Web 应用程序项目后,没有工具可以更改身份验证机制。只需重新开始一个新项目并将身份验证更改为组织帐户(对于本地,如我的情况)。 您的 STS(例如 ADFS 安装)必须已安装且可访问才能完成此向导。 如果您因为无权将计算机加入域而在 VM 中一起破解测试 ADFS DC,请使用 hosts 文件将 VM 的 IP 的 DNS 覆盖为预期的域名。 “每次登录时都要求用户提供凭据”在解决登录注销问题时很有帮助。 如果您没有任何声明规则,我认为任何声明,甚至身份都不会通过。

1) 是什么问题导致我的应用仍然认为用户未通过身份验证?

如果用户通过身份验证,我的https://localhost:44300/Default/Index/ 操作应该会显示User.Identity 的详细信息(我也尝试过Thread.CurrentPrincipal.Identity)。我有一个登录操作链接,生成为:

var signIn = new SignInRequestMessage(new Uri("https://dc.ad.dev.local/adfs/ls/"), "https://localhost:44300");

return new RedirectResult(signIn.WriteQueryString());

单击此链接确实会将我带到 ADFS 登录页面。登录让我回到我的应用程序。在 Chrome 错误中查看保留的网络活动表明我有一条 RequestSecurityTokenResponse 消息被发送回应用程序,但应用程序的 User.Identity 仍未验证

我配置了一个声明规则:将“传入声明”从“Windows 帐户名称”转换为“名称 ID”作为“临时标识符”。我在嗅探的POST 中看到了<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">DevAD\jdoe</saml:NameIdentifier>。我已经尝试了一堆其他的声明规则,但仍然没有得到身份验证

我没有任何自定义代码来吸收索赔。 我希望拦截一个带有令牌的 POST 到任何应用程序 url 将被框架自动转换为 User.Identity,可能是由这个向导在 Startup.Auth 中生成的代码启动的.cs:

app.UseActiveDirectoryFederationServicesBearerAuthentication(
    new ActiveDirectoryFederationServicesBearerAuthenticationOptions
    
        Audience = ConfigurationManager.AppSettings["ida:Audience"],
        MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"]
    );

但我的一部分怀疑这种期望。这是正确的吗?除了我的默认路由 url 之外,MVC WIF 是否有一个特殊的已知路由来接受我应该使用的此类登录帖子?

2) 怎样才能成功登出?

我还有一个注销操作:

WSFederationAuthenticationModule.FederatedSignOut(new Uri("https://dc.ad.dev.local/adfs/ls/"), new Uri(Url.Action("Index", null, null, Request.Url.Scheme)));

但是在这个https://dc.ad.dev.local/adfs/ls?wa=wsignout1.0&wreply=https%3a%2f%2flocalhost%3a44300%2f 页面上,“发生错误”。事件查看器显示 #364:“在联合被动请求期间遇到错误。”

Protocol Name: 
wsfed 

Relying Party: 

Exception details: 
System.ArgumentException: An item with the same key has already been added.
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.AddSignoutSessionInformation(WSFederationSignOutContextBase context)
   at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.ProcessSignOut(WSFederationSignOutContext context)
   at Microsoft.IdentityServer.Web.PassiveProtocolListener.ProcessProtocolSignoutRequest(ProtocolContext protocolContext, PassiveProtocolHandler protocolHandler)
   at Microsoft.IdentityServer.Web.PassiveProtocolListener.ProcessProtocolRequest(ProtocolContext protocolContext, PassiveProtocolHandler protocolHandler)
   at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)

我的 ADFS 服务 > 证书都设置为相同的证书,我认为是正确的。

=================

顺便说一句,以下应该被动发布到应用程序的内容,对吧?而且,它又是自动吸收的?

<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
    <t:Lifetime>
        <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-07-28T14:29:47.167Z</wsu:Created>
        <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-07-28T15:29:47.167Z</wsu:Expires>
    </t:Lifetime>
    <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
        <wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
            <wsa:Address>https://localhost:44300/</wsa:Address>
        </wsa:EndpointReference>
    </wsp:AppliesTo>
    <t:RequestedSecurityToken>
        <saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="_e2399a27-acac-4390-aa8a-556f41fec2f2" Issuer="http://dc.ad.dev.local/adfs/services/trust" IssueInstant="2014-07-28T14:29:47.167Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
            <saml:Conditions NotBefore="2014-07-28T14:29:47.167Z" NotOnOrAfter="2014-07-28T15:29:47.167Z">
                <saml:AudienceRestrictionCondition>
                    <saml:Audience>https://localhost:44300/</saml:Audience>
                </saml:AudienceRestrictionCondition>
            </saml:Conditions>
            <saml:AttributeStatement>
                <saml:Subject>
                    <saml:NameIdentifier Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">DevAD\jdoe</saml:NameIdentifier>
                    <saml:SubjectConfirmation>
                        <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
                    </saml:SubjectConfirmation>
                </saml:Subject>
                <saml:Attribute AttributeName="name" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
                    <saml:AttributeValue>jdoe</saml:AttributeValue>
                </saml:Attribute>
                <saml:Attribute AttributeName="givenname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
                    <saml:AttributeValue>John Doe</saml:AttributeValue>
                </saml:Attribute>
                <saml:Attribute AttributeName="upn" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
                    <saml:AttributeValue>jdoe@ad.dev.local</saml:AttributeValue>
                </saml:Attribute>
            </saml:AttributeStatement>
            <saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" AuthenticationInstant="2014-07-28T14:29:47.152Z">
                <saml:Subject>
                    <saml:NameIdentifier Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">DevAD\jdoe</saml:NameIdentifier>
                    <saml:SubjectConfirmation>
                        <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
                    </saml:SubjectConfirmation>
                </saml:Subject>
            </saml:AuthenticationStatement>
            <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                    <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
                    <ds:Reference URI="#_e2399a27-acac-4390-aa8a-556f41fec2f2">
                        <ds:Transforms>
                            <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                            <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                        </ds:Transforms>
                        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                        <ds:DigestValue>+ZDduF0CKxXq7P+diyAXN51mo549pvwo3BNCekWSEpk=</ds:DigestValue>
                    </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>VMjCbSZXw3YROHYQ1eCYH5D9UQl1tzqZ9Nw99FUK78A8TSLs1ns3G8PE1d1Z1db2KKpbnzExXSXG2elP3Z69OejSWjsywIFTPeGcbGk4BvrV4ZcHGCbYKN0Wg5pySMEqm4LV1E5k+32kuALveLi5fkQROyXudquvVRgYrgu7XBsfr96Uvqo1yWmAzhhpEorfe4Z0p4RurKRpS7IsrI9SkssGOdQV/89NQelIZSZzOEMfay/AxewBbQ8C46g/4NgygaaPsG8X52EFVftzFY0BM8k+aMMUiKrJ0Xo7tJCMxJLcQ3aJdLBRNybHaklFgtln0ZCSlYylglUjUZ5d66jGcg==</ds:SignatureValue>
                <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                    <X509Data>
                        <X509Certificate>MIIC7jCCAdagAwIBAgIQLB+dBr0GI75OvLElC1HZHTANBgkqhkiG9w0BAQsFADAzMTEwLwYDVQQDEyhBREZTIFNpZ25pbmcgLSBkYy5hZC5lbnRlcnByaXNlZGV2LmxvY2FsMB4XDTE0MDcyNDIxMTMxM1oXDTE1MDcyNDIxMTMxM1owMzExMC8GA1UEAxMoQURGUyBTaWduaW5nIC0gZGMuYWQuZW50ZXJwcmlzZWRldi5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALvkkbfrr5YZWNkfv7LFQlVj3qTcfduRltKfAGiK/NOXNp498uMY+zhUBtiPU1woJhsoqfahgQpy3YJhIPsxbVGSXjAGcFVcUq03V2xVJB6+tW1Ny+/lqiXrdvYAHcZvqpeG/tnh5/hGi/mapd2oMxWIWkyRdztJrN+BCzUi4mm80bYrYX8liuDAcJEk5EYh73gaOwzIyUAZvOXwX1UWh9FA8j2mIMyv3b4SgjFQMPT+Fyw4L1cX+3u/PhGlVRSUEAu+igfMxM1JTco+3HMfQuBZLGd8YXhig+6WbIGlcGUhHEdNSr9ymljJBaps1JfGZk7Rj/7hYeHCXbl3mKK7yFUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAU5gYs7BZZBrrm+eDZM5pTaQfnwyeHYWHe9D2UDweWTNjj9KVC2sucUI2K9MXzA3kZOP7UIvnLmHvxG7cnPen095NBIyYYDjzvlImGwq297m6cz0m2ZxkBGMKq9bVSPoVOgDrX0c+e2wFjRgVojd1bWm9fbMvIUWn8KyMQMquXmyJxX5sPxpMfm95yheyh6q67VzgWF9TcUp6jNdmMcRowHWnQ9UVYf1UEMcPUlaljARVQYNQjyHjrcFaRkxF57EkjO3e263KIe0knVNoz8W57prXJLOHOqSe2f4kSKUdU+Xt8XQbJ77xHPdSOoW8NwKZVL7/9TrfVJ6pi1Ob/+LrAA==</X509Certificate>
                    </X509Data>
                </KeyInfo>
            </ds:Signature>
        </saml:Assertion>
    </t:RequestedSecurityToken>
    <t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
    <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
    <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
</t:RequestSecurityTokenResponse>

================

以下是定义的声明。正如@nzpcmad 所建议的那样,第二个现在“将 LDAP 属性作为声明发送”从“Active Directory”发送“SAM-Account-Name”作为“名称”,“显示名称”作为“Given Name”和“User-主体名称”为“UPN”。虽然应用程序收到了被动帖子中的声明,但User.Identity.IsAuthenticated 仍然是错误的,其他User.Identity 数据也是空白的。

【问题讨论】:

您是否找到解决退出时遇到的错误的方法? 您好,有关于这个问题的消息吗?你终于解决了吗? 不,抱歉。我放弃了 【参考方案1】:

您的观察非常正确。

请注意:

ADFS 在 Server 2008 R2、2012 和 2012 R2 上运行。

看看Use the On-Premises Organizational Authentication Option (ADFS) With ASP.NET in Visual Studio 2013。

它准确地描述了你想要做什么。

特别是,请查看声明。

您会看到它使用“发送 LDAP 属性”而不是您使用的转换。

【讨论】:

谢谢,我添加了额外的声明,但它仍然无法正常工作。我在问题中添加了这些细节。 查看msdn.microsoft.com/en-us/library/hh291061(v=vs.110).aspx 了解如何处理 IsAuthenticated。 是的,这就是我正在使用的 View 实现。控制器正在向 ViewBag 添加Thread.CurrentPrincipal.IdentityUser.Identity(我相信两者都应该工作),如图所示。根据我的第二个要点,我没有做任何配置文件。 我刚刚根据链接构建了一个项目,它工作正常。我建议您按照链接创建一个新项目,然后与您的项目进行比较,看看有什么不同。 我会再试一次(msdn.microsoft.com/en-us/library/hh291061(v=vs.110).aspx,即),但即便如此,从品牌生成的代码带有本地组织身份验证的新 MVC 5 项目模板似乎表明不需要更改任何 .config 文件。【参考方案2】:

我遇到了同样的注销问题,如果您在受信任的人证书存储中没有颁发证书,似乎会发生这种情况。

【讨论】:

以上是关于MVC 5、WIF (System.IdentityModel) 和 ADFS 未实际进行身份验证,联合注销时出错的主要内容,如果未能解决你的问题,请参考以下文章

使用 WIF 和 jquery ajax 请求时 ASP.NET MVC 3 中的会话 Cookie 过期处理

有啥方法可以在 WIF 4.5 上支持 JWTSecurityTokenHandler 吗?

带有 WIF 4.5 的 WCF 数据服务;没有为 POST 请求设置主体

ABP集成WIF实现单点登录

Android以太网和wifi共存并设置Wif优先级最高

使用WIF,audienceUris和realm有啥区别?