【问题标题】:Too many OpenID.nonce cookies cause "Bad Request"太多 OpenID.nonce cookie 导致“错误请求”
【发布时间】:2017-08-01 11:26:10
【问题描述】:

我已经浏览了与我遇到的问题相关的链接 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. 我输入网站 URL,将我重定向到 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. 现在再次输入网站 URL,将我重定向到身份服务器登录页面。 (如第 1 步)
  8. 我输入凭据并点击登录。
  9. 成功登录后,IdentityServer 向网站进行 POST,网站创建 AuthenticationTicket。然而,这里HttpContext.Current.Request.IsAuthenticated 是假的,所以Default.aspx 页面重定向到IdentityServer。我已经登录,因此 Indetityserver 重定向到客户端网站并继续循环。

Fiddler 展示了从 identityServer 到网站的 default.aspx 页面的多次往返。每次往返都会不断添加OpenIdConnect.nonce.OpenIdConnect cookie,最终由于最大请求大小而出现错误的请求错误。

因此,正如上述链接中所建议的,我在客户端应用程序中将 Microsoft.Owin.Security.OpenIdConnect 降级为 3.0.0

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

【问题讨论】:

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


【解决方案1】:

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

该错误使 Owin 设置的 cookie 在某些情况下神秘消失。

此中间件是针对该错误的修复程序。只需在任何 cookie 处理中间件之前添加它,它将保留身份验证 cookie。

app.UseKentorOwinCookieSaver();

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

【讨论】:

  • 我花了几天时间尝试调试我们的 Owin 中间件正在授权用户但身份验证 cookie 丢失的情况。我安装了上面的 NuGet 包,现在它可以工作了!谢谢你。
  • @Narendra 我尝试安装 nuget 包 Kentor.OwinCookieSaver 但我收到错误 Severity Code Description Project File Line Suppression State Error Could not install package 'Kentor.OwinCookieSaver 1.1.1'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5.1', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author. 0
【解决方案2】:

为我解决问题的是使用 AdamDotNet 的自定义 OpenIdConnectAuthenticationHandler 删除旧的 nonce cookie。

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

【讨论】:

    猜你喜欢
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 2020-04-22
    • 1970-01-01
    • 2018-08-09
    相关资源
    最近更新 更多