首页 文章

太多cookie OpenIdConnect.nonce导致错误页面“Bad Request - Request Too Long”

提问于
浏览
12

我在C#ASP MVC Web应用程序中使用OWIN / OAuth和OpenId Connect身份验证( Microsoft.Owin.Security.OpenIdConnect ) . 使用Microsoft帐户登录SSO基本上可以正常工作,但我不时会在浏览器上显示 Bad Request - Request Too Long 的错误页面 .

我发现这个错误是由太多的cookie引起的 . 删除cookie有一段时间了,但过了一段时间后问题又回来了 .

导致问题的cookie是从OpenId框架设置的,因此有许多名称为 OpenIdConnect.nonce.9oEtF53WxOi2uAw....... 的cookie .

这不是SPA应用程序,但是某些部分会定期使用ajax调用进行刷新 .

2 回答

  • 0

    事实证明,根本原因是Ajax调用 .

    The problematic flow was

    1)OAuth cookie在一段时间后过期了

    2)到期通常会导致页面重定向到 login.microsoft.com 以刷新cookie . 在这一步OAuth框架 adds new nonce cookie响应(每次)!

    3)但是Ajax不处理域外的重定向(跨域到 login.microsoft.com ) . 但cookie已经附加到页面上 .

    4)下一个周期性Ajax调用重复该流程,导致'nonce'cookie快速增加 .

    Solution

    我不得不扩展“OWIN OpenId”框架设置代码以不同方式处理Ajax调用 - 以防止重定向并停止发送cookie .

    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
    
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = ctx => 
                    {
                        bool isAjaxRequest = (ctx.Request.Headers != null && ctx.Request.Headers["X-Requested-With"] == "XMLHttpRequest");
    
                        if (isAjaxRequest)
                        {
                            ctx.Response.Headers.Remove("Set-Cookie");
                            ctx.State = NotificationResultState.HandledResponse;
                        }
    
                        return Task.FromResult(0);
                    }
                }
            });
    }
    

    必须调整Ajax调用者以检测 401 代码并执行整页刷新(这导致快速重定向到Microsoft权限) .

  • 33

    在我的情况下,问题是我在 Startup.cs 中配置应用程序的顺序 .

    提醒自己 - 始终首先配置身份验证!

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = _clientId,
                    ClientSecret = _clientSecret,
                    Authority = _authority,
                    RedirectUri = _redirectUri
                });
    
            // configure the rest of the application...
        }
    

相关问题