瞬时无限登录循环Azure上的应用服务 - OpenIDConnect验证与Azure的AD(Tr

2019-10-30 12:40发布

背景

因此,我们必须从Azure的AD认证使用OpenIdConnect另一个租户应用程序的服务。

登录工作在IIS的一个开发实例,它适用于我们的测试应用程序的服务。 我们看到测试上的问题,它消失了,在项目的整个测试阶段没有返回。

现在,我们已经部署到生产,我们再次看到了问题。

问题

我们看到的是,一切都将正常工作一段时间,然后几个小时后,这个问题将再次出现。

我们有一个解决办法修复,恢复服务 - 这是让然后在蔚蓝色的控制面板禁用应用服务认证。 与此相反的作品太 - 禁用,然后再启用将恢复服务。

编码

public void ConfigureAuth(IAppBuilder app)
        {
            //Azure AD Configuration
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());


            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    //sets client ID, authority, and RedirectUri as obtained from web config
                    ClientId = clientId,
                    ClientSecret = appKey,
                    Authority = authority,
                    RedirectUri = redirectUrl,

                    CallbackPath = new PathString("/"), //use this line for production and test


                    //page that users are redirected to on logout
                    PostLogoutRedirectUri = redirectUrl,

                    //scope - the claims that the app will make
                    Scope = OpenIdConnectScope.OpenIdProfile,
                    ResponseType = OpenIdConnectResponseType.CodeIdToken,

                    //setup multi-tennant support here, or set ValidateIssuer = true to config for single tennancy
                    TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuer = true,
                        //SaveSigninToken = true
                    },
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthenticationFailed = OnAuthenticationFailed,
                        AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                    }
                }
                );
        }

        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
        {
            var code = context.Code;
            ClientCredential cred = new ClientCredential(clientId, appKey);
            string userObjectId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
            //this token cache is stateful, we're going to populate it here, but we'll store it elsewhere in-case the user ends up accessing a different instance
            AuthenticationContext authContext = new AuthenticationContext(authority, new NaiveSessionCache(userObjectId));

            // If you create the redirectUri this way, it will contain a trailing slash.  
            // Make sure you've registered the same exact Uri in the Azure Portal (including the slash).
            Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
            AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, cred, "https://graph.windows.net");

            //populate the persistent token cache
            testdb2Entities5 db = new testdb2Entities5();
            PersistentTokenCache tc = await db.PersistentTokenCaches.FindAsync(userObjectId);
            //if null, populate a new item
            if (tc == null)
            {
                tc = new PersistentTokenCache();
                tc.object_id = userObjectId;
                tc.token = code;
                db.PersistentTokenCaches.Add(tc);
                await db.SaveChangesAsync();

            }
            else
            {
                tc.token = code;
                await db.SaveChangesAsync();
            }

        }

        //authentication failed notifications
        private Task OnAuthenticationFailed(AuthenticationFailedNotification<Microsoft.IdentityModel.Protocols
                                                                            .OpenIdConnect.OpenIdConnectMessage,
                                                                            OpenIdConnectAuthenticationOptions> context)
        {
            context.HandleResponse();
            context.Response.Redirect("/?errormessage=" + context.Exception.Message);
            return Task.FromResult(0);
        }

问题

所以,无论基于何种启用和禁用应用程序,服务认证呢,它显然是临时固定的东西。 所以我想这是一个cookie相关的问题 - 因为那将会会话之间传递状态的唯一的事情。 在地球上,这可能是这里的问题? 而哪些步骤我需要诊断和解决问题?

Answer 1:

到目前为止,好像这是一个问题,在武士刀一个已知的bug,其中武士刀cookie管理器和ASP.NET的cookie管理器的冲突和互相覆盖的cookie。

下面是一些故障排除,你可以参考一下:

1.设置app.UseCookieAuthentication(new CookieAuthenticationOptions {CookieSecure == CookieSecureOption.Always}) 这意味着该cookie可以随着你的权威性泄漏。

2.增加SystemWebCookieManagerUseCookieAuthentication这是在Microsoft.Owin.Host.SystemWeb NuGet包。 请参阅此线程 。

3. 拆分的cookie 。 有人注意到,这是问题,如果Cookie的字符比浏览器限制(> 4096)等等。 因此,要解决这个问题,在设置Cookie与每个各地4000个字符,并在需要的时候所有的cookie相结合,以获得原始值。

有关如何与微软添加登录到ASP.NET Web应用程序的详细信息,请参阅本文章 。

更新

固定用安装Kentor.OwinCookieSaver NuGet包并添加app.UseKentorOwinCookieSaver(); 之前app.UseCookieAuthentication(new CookieAuthenticationOptions());



文章来源: Transient Infinite Login Loop on Azure App Service - OpenIDConnect Auth with Azure AD