【问题标题】:OWIN OpenId Authentication - Active Session after logoutOWIN OpenId 身份验证 - 注销后的活动会话
【发布时间】:2020-03-11 22:00:51
【问题描述】:

我在我的应用程序中实现了 ASP.Net Cookie 身份验证和 OWIN OpenId 身份验证的混合。我正在尝试修复一个安全漏洞,即即使在注销后会话也不会失效。

中间件实现:

app.UseCookieAuthentication(
    新的 CookieAuthenticationOptions
    {
        AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
        app.UseOpenIdConnectAuthentication(新的 OpenIdConnectAuthenticationOptions
        {
            客户 ID = 客户 ID,
            权威=权威,
        }
     }
);

退出代码(基于用户类型):

HttpContext.GetOwinContext().Authentication.SignOut(
    OpenIdConnectAuthenticationDefaults.AuthenticationType,
    CookieAuthenticationDefaults.AuthenticationType);
    
HttpContext.GetOwinContext().Authentication.SignOut(
    CookieAuthenticationDefaults.AuthenticationType);

我正在 Fiddler 中捕获流量并单击从网页退出。当我尝试从 Fiddler 重新发出请求时,它成功完成并且在 HttpModule 中,Application.User.Identity.IsAuthenticatedTrue

我有几个问题:-

  1. 这是 Cookie 重放攻击吗?
  2. 我做错了什么,如果不是我会 必须通过一些 hack 来修复它,比如在缓存中存储一​​个 cookie 和 比较一下?

【问题讨论】:

标签: c# asp.net asp.net-mvc asp.net-identity owin


【解决方案1】:

不确定这个答案是否可以帮助其他人,但这里link 提供了有关如何使用 MVC 应用程序设置 openId 的更多信息。

更改中间件配置

startup.cs 文件中添加 OpenId & Cookies 认证中间件。将 ResponseType 设置为 Id_token 以使 openId 注销也可以工作。

app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                CookieHttpOnly = true,
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                CookieName = "AppCookies",
                ExpireTimeSpan = TimeSpan.FromMinutes(30),
                SlidingExpiration = true
            });

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://localhost:44319/identity",
                
    ClientId = "mvc",
    Scope = "openid profile roles",
    RedirectUri = "https://localhost:44319/",
    ResponseType = "id_token",
    SignInAsAuthenticationType = "Cookies",
    UseTokenLifetime = false,
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        SecurityTokenValidated = n =>
            {
                var id = n.AuthenticationTicket.Identity;

                // we want to keep first name, last name, subject and roles
                var givenName = id.FindFirst(Constants.ClaimTypes.GivenName);
                var familyName = id.FindFirst(Constants.ClaimTypes.FamilyName);
                var sub = id.FindFirst(Constants.ClaimTypes.Subject);
                var roles = id.FindAll(Constants.ClaimTypes.Role);

                // create new identity and set name and role claim type
                var nid = new ClaimsIdentity(
                    id.AuthenticationType,
                    Constants.ClaimTypes.GivenName,
                    Constants.ClaimTypes.Role);

                nid.AddClaim(givenName);
                nid.AddClaim(familyName);
                nid.AddClaim(sub);
                nid.AddClaims(roles);

                // add some other app specific claim
                nid.AddClaim(new Claim("app_specific", "some data"));                   

                n.AuthenticationTicket = new AuthenticationTicket(
                    nid,
                    n.AuthenticationTicket.Properties);
                
                return Task.FromResult(0);    
            },
            RedirectToIdentityProvider = n =>
                {

                    // if signing out, add the id_token_hint
                    if ((int)n.ProtocolMessage.RequestType ==                     (int)OpenIdConnectRequestType.Logout)
                    {
                        var idTokenHint = n.OwinContext.Authentication.User.FindFirst(Startup.IdToken);

                        if (idTokenHint != null)
                        {
                            n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                        }
                    }
                    return Task.FromResult(0);
                }
    }
});

添加注销

添加注销很简单,只需在 Katana 身份验证管理器中添加一个调用 Signout 方法的新操作即可:

public ActionResult Logout()
{
           Session.Abandon();
    
            // clear session cookie (not necessary for your current problem but i would recommend you do it anyway)
            HttpCookie cookie2 = new HttpCookie("ASP.NET_SessionId", "");
            cookie2.HttpOnly = true;
            cookie2.Expires = DateTime.Now.AddYears(-1);
            Response.Cookies.Add(cookie2);

            // clear site cookie
            var siteCookie = new HttpCookie("AppCookies", "");
            siteCookie.HttpOnly = true;
            siteCookie.Expires = DateTime.Now.AddYears(-1);
            Response.Cookies.Add(siteCookie);
            
            Request.GetOwinContext().Authentication.SignOut();
            return Redirect("/");
}

【讨论】:

    【解决方案2】:

    从您的应用程序中注销时,您也必须从身份服务器中注销。否则,您的应用程序将被重定向到身份服务器,重新进行身份验证并重新登录。检查通知下的以下代码sn-p:

    app.UseCookieAuthentication(
        new CookieAuthenticationOptions
        {
            AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,    
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
            },
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                RedirectToIdentityProvider = n =>
                {
                    // if signing out, add the id_token_hint
                    if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                    {
                        var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
    
                        if (idTokenHint != null)
                        {
                            n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                        }
                    }
    
                    return Task.FromResult(0);
                }
            }
         }
    );
    

    您会发现一些 OWIN 中间件设置示例(虽然不是您问题的直接答案)here

    【讨论】:

    • 感谢您的回答。我将idTokenHint 设为空。有什么我需要配置的吗?另外,如果设置了,我需要再次检查,否则 Identity 会处理?
    • 您必须将“id_token”添加为声明,以便在注销时将我取回并传递给 id 服务器。请查看我的答案下方链接中的示例。它有详细的代码示例。
    猜你喜欢
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    • 2010-12-07
    • 2013-04-01
    • 2015-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多