Azure ACS自定义身份提供程序Single SignOut

时间:2013-05-07 13:33:53

标签: azure claims-based-identity acs

我正在基于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&amp;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,最后回到我的应用程序)

两个主要问题:

  1. 为什么调用ACS注销会给我带iframe的iframe页面 wa = wsignoutcleanup1.0 for google / live但是302重定向到我的 身份提供者,可能是我想念的东西 FederationMetadata.xml?
  2. 在步骤3之后看起来像ACS没有 了解我已成功退出我的身份提供商 从这一刻开始尝试一次又一次地做,如何告诉他们 停止它?

1 个答案:

答案 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重载非常重要。而不是在您对用户进行一般性注销时。

请尝试所有提及的更改,如果它能解决您的问题,请告诉我们!