首页 文章

如何使用Thinktecture Identity Server3和OpenId实现单点注销,用于多个ASP.NET MVC应用程序的中间件

提问于
浏览
1

我有2个ASP.NET MVC应用程序,我使用OpenID中间件 UseOpenIdConnectAuthentication 对两者进行单点登录 . 配置如下所述 . SSO效果很好 . 我从应用程序1登录然后检查我是否登录到连接到idserver的应用程序2,我可以看到自己登录 . 两个客户端应用程序现在都具有相同的id_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设置为IdTokenHint,如下所示:

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);
            }

Problem area > Single Logout:

Success Scenario: 当我从应用程序1注销时,它会重定向到idserver并将我注销并将我重定向回应用程序1.在调试时,我可以看到DefaultViewService的logout方法中的注销消息在这种情况下不为null . 这非常有效 .

Failure Scenario: 问题是当我尝试从应用程序2而不是应用程序1注销时(请记住我从应用程序1登录),它确实将我带到了idserver的注销页面,我可以注销 . 但它不会重定向回应用程序2并保留在idserver注销页面上 . 在调试时,我可以看到DefaultViewService的logout方法中的注销消息在这种情况下为null .

是不是因为id_token最初发给了application1?

我错过了什么?我是否需要处理这种情况并以某种方式获取用户使用的身份服务器中的客户端实际注销(应用程序2)?然后可能会发布一个新的SignoutMessage并为该客户端添加postlogout重定向Url?

或者我弄错了,这应该自动运行?

Update: 一个大错是尝试将IISExpress localhost上的所有内容都放在不同的端口上,两个客户端(locahost,不同的端口)以某种方式获得相同的id_token和访问令牌,这不应该发生 .

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

我仍然致力于单点注销,探索iFrame方法 .

1 回答

  • 0

    几天来,我一直在努力解决这个问题 . 谷歌搜索指出我的问题:)

    这就是我所做的对我有用的东西(不确定这是否是正确的方法):

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

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

相关问题