我正在基于Thinktecture代码实现自己的身份提供程序。以下是使用单点登出功能时Azure ACS的一种奇怪行为,它与google / live和我自己的身份提供商不同。
注销的URL(领域与网站名称完全相同):
mysite.accesscontrol.windows.net/v2/wsfederation?wa=wsignout1.0&wreply=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f&wtrealm=http%3a%2f%2flocalhost%2fAdministration .Frontend.Web%2F
这是一个用于注销的伪代码:
//clear FedAuth cookies
FormsAuthentication.SignOut();
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(true);
//call Single SignOut
var signoutRequestMessage = new SignOutRequestMessage(new Uri(signOutUrl));
return Redirect(signoutRequestMessage.WriteQueryString());
以下是示例流程(我使用隐私浏览和Fiddler查看所有内容):
1)我正在使用Google帐户登录我的应用程序。
2)点击注销,结果我在ACS上获得了一个带有此代码的页面:
function on_completion()
{window.location = 'http://localhost/Administration.Frontend.Web/';}
<iframe src="https://www.google.com/accounts/Logout" style="visibility: hidden"">/iframe>
<iframe src="http://localhost/Administration.Frontend.Web/?wa=wsignoutcleanup1.0" style="visibility: hidden"></iframe>
结果:我已从我的应用程序和谷歌退出。
3)登录我的身份提供者,单击注销,重定向到ACS上的相同URL,与上一步一样,但现在我得到302结果,重定向到
https://localhost/IdentityProvider/issue/wsfed?wa=wsignout1.0&wreply=https%3a%2f%2fmysite.accesscontrol.windows.net%2fv2%2fwsfederation%3fredirectUrl%3dhttp%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f
结果:我已从我的应用程序和我的身份提供商处注销。
4)尝试再次使用谷歌,通过输入凭证成功登录,但如果失败则退出。我已从应用程序注销但未从谷歌登录。而且我也看到我没有获得iframe的页面,而是ACS再次尝试将我重定向到
https://localhost/IdentityProvider/issue/wsfed?wa=wsignout1.0
(然后回到mysite.accesscontrol.windows.net,最后回到我的应用程序)
两个主要问题:
答案 0 :(得分:3)
这是你必须做的。
首先,使用联合身份验证时始终使用HTTPS!有时协议协商会失败只是因为它是普通的HTTP。有时浏览器会阻止非安全流量,这对于签名流程至关重要。所以,总是使用HTTPS!
现在,要实现单点登出的形式,你希望你做更多的工作。
您的退出网址:
mysite.accesscontrol.windows.net/v2/wsfederation?wa=wsignout1.0&wreply=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f&wtrealm=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f
不要将它用作构造SignOutRequestMessage的参数。直接使用它return Redirect(signOutUrl)
!
您必须在两个主要地方实施退出!
首先是你的一般logOff动作方法(假设你正在使用MVC)类似于你已经拥有但有重大改变的东西:
FormsAuthentication.SignOut();
var signoutProtocolLocation = "https://[your_acs_namespace].accesscontrol.windows.net:443/v2/wsfederation?wa=wsignout1.0&wtrealm=[realm]&wreply=[reply]";
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(signoutProtocolLocation);
请注意,我在这里使用带string
paramer`的重载将结果重定向到ACS SSO位置!
现在非常ACS SSO
位置将使用JS和几个iframe
元素生成上述HTML页面。其中一个将是:
<iframe src="http://localhost/Administration.Frontend.Web/?wa=wsignoutcleanup1.0" style="visibility: hidden"></iframe>
现在,特定位置http://localhost/Administration.Frontend.Web/?wa=wsignoutcleanup1.0
是代码中第二个实现SSO的位置。此请求必须不重定向到登录页面,但必须正确处理并返回200或301响应(反过来将返回200!)!为简单起见,我只会粘贴此处使用的代码:
if(Request.QueryString.AllKeys.Contains("wa")
&& Request.QueryString["wa"].Equals("wsignoutcleanup1.0"))
{
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(true);
return RedirectToAction("Index");
}
在请求SignOut(true)
操作时,仅使用 true 调用wsignoutcleanup
重载非常重要。而不是在您对用户进行一般性注销时。
请尝试所有提及的更改,如果它能解决您的问题,请告诉我们!