太多OpenID.nonce cookie导致“错误请求”

时间:2017-03-11 00:24:41

标签: c# asp.net-identity owin identityserver3 openid-connect

我已经浏览了与我遇到的问题相关的链接hereherehere

我使用IdentiServer3进行身份验证的Silverlight应用程序,当我实现注销功能时,我刚开始遇到这个问题。请注意,该问题与Silverlight无关,因为登录和注销功能实际上是在服务器端实现的,这是一个传统的ASP.Net Web表单。 (.NET 4.5.1)

应用程序从未具有注销功能,因此用户只是用来关闭浏览器,所以我们以前从未遇到过这个问题。我们现在有logout.aspx页面,Silverlight应用程序已链接到此页面。

Logout.aspx页面

public partial class Logout : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.IsAuthenticated)
        {
            Session.Clear();
            Request.GetOwinContext().Authentication.SignOut();
        }
        Response.Redirect("/");
    }
}

Default.aspx页面。这是首页

public partial class Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Send an OpenID Connect sign-in request.
        if (!System.Web.HttpContext.Current.Request.IsAuthenticated)
        {
            HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }
    }
} 

配置OpenID连接的OWIN启动类

  app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies",
            LoginPath = new Microsoft.Owin.PathString("/Default.aspx")
        });

  app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            Authority = ConfigurationManager.AppSettings["Authority"],
            Scope = "openid profile",
            ClientId = ConfigurationManager.AppSettings["ClientId"],
            RedirectUri = ConfigurationManager.AppSettings["RedirectUri"],
            ResponseType = "id_token",
            SignInAsAuthenticationType = "Cookies",

            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = (context) =>
                {

                    var id = context.AuthenticationTicket.Identity;

                    // create new identity
                    var newIdentity = new ClaimsIdentity(id.AuthenticationType);

                    // we want to keep username and subjectid                        
                    var sub = id.FindFirst(ClaimTypes.NameIdentifier);
                    var username = id.FindFirst("preferred_username");
                    newIdentity.AddClaim(username);
                    newIdentity.AddClaim(sub);

                    // keep the id_token for logout
                    newIdentity.AddClaim(new Claim("id_token", context.ProtocolMessage.IdToken));

                    context.AuthenticationTicket = new AuthenticationTicket(
                        newIdentity,
                        context.AuthenticationTicket.Properties);

                    return Task.FromResult(0);
                },

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

重现问题的步骤:

  1. 我输入网站网址,将我重定向到identityserver3登录 页。
  2. 我输入凭据并点击登录。
  3. 成功登录后我 被重定向到网站,然后我点击退出。
  4. 我被记录了 成功了。 Fiddler显示以下电话

    https://idsvr.mydomain.com/identity/connect/endsession?id_token_hint=XXXXXXXXXXXXXX https://idsvr.mydomain.com/identity/logout?id=616dd9a4e4c6a55b0bb27faceb4df8dd https://idsvr.mydomain.com/identity/connect/endsessioncallback?sid=xxxxxx

  5. 我按预期登陆https://idsvr.mydomain.com/identity/logout?id=xxxxxxx页面。

  6. 现在我关闭浏览器(这一步很重要)
  7. 现在再次输入网站网址,将我重定向到身份服务器登录页面。 (如第1步)
  8. 我输入凭据并点击登录。
  9. 成功登录后,IdentityServer对网站进行POST,网站创建AuthenticationTicket。但是,此处HttpContext.Current.Request.IsAuthenticated为false,因此Default.aspx页面重定向到IdentityServer。我已登录,因此Indetityserver重定向到客户端网站并继续循环。
  10. Fiddler展示了从identityServer到网站default.aspx页面的几次往返。每次往返都会不断添加OpenIdConnect.nonce.OpenIdConnect Cookie,最终由于最大请求大小而导致错误请求错误。

    正如上面链接所示,我在客户端应用程序中将Microsoft.Owin.Security.OpenIdConnect降级为3.0.0

    然而,我仍然陷入持续循环中。唯一的区别是现在它不会为每次往返添加新的OpenIdConnect.nonce.OpenIdConnect cookie。 Fiddler每次往返只显示一个饼干。但是HttpContext.Current.Request.IsAuthenticated仍然是假的。所以我陷入了连续循环。

2 个答案:

答案 0 :(得分:5)

我的asp.net mvc应用程序遇到了类似的问题。经过一些研究后,我发现微软的Owin实现System.Web存在一个错误。在IIS上运行Owin应用程序时使用的那个。如果我们在ASP.NET MVC5中使用基于Owin的新身份验证处理,那么我们99%的人可能会这样做。

臭虫使Owin设置的cookie在某些情况下神秘地消失。

这个中间件是对该bug的修复。在任何处理中间件的cookie之前简单地添加它,它将保留身份验证cookie。

app.UseKentorOwinCookieSaver();

这是详细链接 https://github.com/KentorIT/owin-cookie-saver

答案 1 :(得分:0)

为我解决问题的是使用AdamDotNet的Custom OpenIdConnectAuthenticationHandler删除旧的现时cookie。

https://stackoverflow.com/a/51671887/4058784