IdentityServer3 注销功能不适用于 ASP.NET Core 客户端

Posted

技术标签:

【中文标题】IdentityServer3 注销功能不适用于 ASP.NET Core 客户端【英文标题】:IdentityServer3 logoff functionality does not work with ASP.NET Core client 【发布时间】:2017-07-29 16:55:05 【问题描述】:

我正在使用 IdentityServer 3 进行身份验证。我有 2 个客户端应用程序,一个是使用经典的 ASP.NET MVC 5 开发的,另一个是使用 ASP.NET Core 开发的。这两个应用程序都实现了如下注销功能:

经典 ASP.NET MVC 5

应用启动

public class Startup

    public void Configuration(IAppBuilder app)
            
        var CK = new CookieAuthenticationOptions()
        
            AuthenticationType = "Cookies",
            CookieName = "MyCookie"
        ;

        app.UseCookieAuthentication(CK);

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        
            Authority = "https://login.mydomain.com/identity",
            Scope = "openid profile",
            ClientId = "myclientid",
            RedirectUri = "http://localhost:34937/",
            ResponseType = "id_token",
            SignInAsAuthenticationType = "Cookies",

            Notifications = new OpenIdConnectAuthenticationNotifications
            
                SecurityTokenValidated = (context) =>
                
                    // do claim transformation here
                ,

                RedirectToIdentityProvider = (n) =>
                
                    if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                    
                        var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
                        n.ProtocolMessage.IdTokenHint = idTokenHint;
                    
                    return Task.FromResult(0);
                
            
     
 

帐户控制器具有注销操作

  public class AccountController:Controller
  
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    
        Request.GetOwinContext().Authentication.SignOut();
        return Redirect("/");
    
  

ASP.NET Core

应用程序启动

    public static class IApplicationBuilderExtensions
    
        public static void UseIdentityServer(this IApplicationBuilder app, string authority, string clientId)
        
            app.UseCookieAuthentication(new CookieAuthenticationOptions()
            
                AutomaticAuthenticate = true,
                AutomaticChallenge = true,
                AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme,
                LoginPath = "/home",
                AccessDeniedPath = new PathString(IdentityConstant.AccessDeniedPath),
                CookieName = "MtAuthCookie",
                SlidingExpiration = true
            );

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();           

            var connectOptions = new OpenIdConnectOptions()
                            
                AutomaticChallenge = true,
                Authority = authority,
                ClientId = clientId,
                ResponseType = "id_token",
                AuthenticationScheme = OpenIdConnectDefaults.AuthenticationScheme,
                SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme,             
                CallbackPath = "/home",
                Events = new OpenIdConnectEvents()
                
                    OnTokenValidated = async context =>
                    
                        //create new identity to store only required claims here.                       
                    ,
                    OnRedirectToIdentityProvider = async context =>
                    
                        if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                        
                            var idTokenHint = context.HttpContext.User.FindFirst("id_token");
                            if (idTokenHint != null)
                                context.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                        
                        await Task.FromResult(0);
                                        
                
            ;        


            app.UseOpenIdConnectAuthentication(connectOptions);
        
    

Account Controller 有注销操作

  public class AccountController:Controller
  
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> LogOff()
    
        if (User.Identity.IsAuthenticated)
        
            await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        
        return Redirect("/");
    
  

问题 在经典的 asp.net 注销操作中运行良好。我看到它执行OnRedirectToIdentityProvider 事件,并且context.ProtocolMessage.RequestType 设置为LogoutRequest,之后它发出GET 请求:

https://login.mydomain.com/identity/connect/endsession?id_token_hint=XXXXXXXXXXXXXXhttps://login.mydomain.com/identity/logout?id=XXXXXXhttps://login.mydomain.com/identity/connect/endsessioncallback?sid=XXXXXX

最后用户登陆https://devlogin.crowdreason.com/identity/logout?id=xxxx页面

但是在 ASP.NET Core https://login.mydomain.com/identity/connect/endsession 中永远不会在注销操作时被调用。我还注意到context.ProtocolMessage.RequestType 永远不会设置为Logout。 事实上,注销用户会自动获得身份验证并返回主页?

还有

我在 ASP.NET Core 中缺少什么?是否有使用IdentityServer3ASP.NET Core 客户端的示例? (注意我没有使用 IdentityServer4)

【问题讨论】:

【参考方案1】:

我认为有一个不同的事件。这对我有用:

OnRedirectToIdentityProviderForSignOut = context =>
                
                    var idTokenHint = context.HttpContext.User.FindFirst("id_token");

                    if (idTokenHint != null)
                    
                        context.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                    

                    return Task.FromResult(0);
                

【讨论】:

以上是关于IdentityServer3 注销功能不适用于 ASP.NET Core 客户端的主要内容,如果未能解决你的问题,请参考以下文章

注销功能不适用于 ASP.NET 标识

注销功能不适用于 ASP.NET 标识

从选项卡注销,不适用于所有其他选项卡

IdentityServer3 注销端点上没有自动重定向

带有IdentityServer3的Oidc-client - Angular2,如何正确注销和登录

Keycloak 注销不适用于公开 REST 服务的“仅承载”应用程序