如何使用Thinktecture Identity Server3和OpenId自带中间件实现多个ASP的单次注销.NE



我有2个ASP。. NET MVC应用程序,我使用OpenID中间件UseOpenIdConnectAuthentication做单点登录到两者。配置说明如下。SSO非常有效。我从应用程序1登录,然后检查我是否也登录到连接到idserver的应用程序2,我可以看到自己登录了。两个客户端应用程序现在都有相同的id_token和token。

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        AuthenticationType = "oidc",
        SignInAsAuthenticationType = "Cookie",
        Authority = "<my-idserver-url>",
        ClientId = "client1",
        RedirectUri = "https://localhost:44360",
        PostLogoutRedirectUri = "https://localhost:44360",                
        ResponseType = "id_token token",
       //scopes from config file
        Scope = ConfigurationManager.AppSettings.Get("Scope"),
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            SecurityTokenValidated = n =>
            {
                var claims = n.AuthenticationTicket.Identity.Claims;
                var accepted_claims = new[]{"name", "tenant", "email", "sub"};
                var new_claims = claims.Where(x => accepted_claims.Contains(x.Type)).ToList();
                new_claims.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
                new_claims.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
                var ci = new ClaimsIdentity(new_claims, n.AuthenticationTicket.Identity.AuthenticationType, "email", "role");
                n.AuthenticationTicket = new AuthenticationTicket(ci, n.AuthenticationTicket.Properties);
                return Task.FromResult(0);
            }

在应用程序中单击注销时,当在客户端调用RedirectToIdentityProvider方法时,我将id_token设置为idtokenint,如下所示:

RedirectToIdentityProvider = n =>
            {
                if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)
                {
                    var user = n.OwinContext.Authentication.User;
                    if (user != null && user.Identity.IsAuthenticated)
                    {
                        var id_token_claim = user.Claims.FirstOrDefault(x => x.Type == "id_token");
                        if (id_token_claim != null)
                        {
                            n.ProtocolMessage.IdTokenHint = id_token_claim.Value;
                        }
                    }
                }
                return Task.FromResult(0);
            }

问题区>单次注销:

成功场景:当我从应用程序1注销时,它将重定向到idserver并注销我,然后重定向回应用程序1。在调试时,我可以看到DefaultViewService的注销方法中的注销消息在这种情况下不是空的。

失败场景:问题是,当我尝试从应用程序2而不是应用程序1注销时(请记住,我是从应用程序1登录的),它确实将我带到idserver上的注销页面,并且我可以注销。但是它不会重定向回应用程序2,而是停留在idserver注销页面上。在调试中,我可以看到DefaultViewService的logout方法中的签出消息在这种情况下是空的。

可能是因为id_token最初是发给应用程序的吗?

我错过了什么?我是否需要处理这种场景,并以某种方式获取用户使用的身份服务器中的客户机,以便实际注销(应用程序2)?然后可能发出一个新的SignoutMessage并为该客户端放入注销后重定向Url ?

或者我完全搞错了,这应该自动工作?

更新:一个错误是在不同端口的IISExpress localhost上尝试这个,两个客户端(localhost,不同端口)以某种方式获得相同的id_token和访问令牌,这不应该发生。

迁移到托管不同站点的IIS解决了这个问题,现在应用程序可以获得自己的独立id_token和访问令牌。

我仍在研究单注销,探索iFrame方法。

我已经为此挣扎了好几天了。谷歌给我指出了你的问题:)

这是我所做的,为我工作(不确定这是否是正确的方法):

为每个客户端配置在PostLogoutRedirectUris中添加了两个客户端uri:

PostLogoutRedirectUris = new List<string>()
{
    "http://localhost:28560/",
    "http://localhost:57311/"
}

最新更新