本文介绍了Azure应用服务上的瞬态无限登录循环-使用Azure AD的OpenIDConnect Auth的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

因此,我们有一个应用程序服务,可以使用OpenIdConnect在另一个租约中从Azure AD进行身份验证。

So we have an app service that authenticates from Azure AD in another tenancy using OpenIdConnect.

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

Login works on a dev instance of IIS, and it works on our test app service. We saw the issue on test, and it vanished and didn't return during the entire testing phase of the project.

现在我们已经部署到生产环境中了,重新看到问题。

Now we've deployed to production, and we're seeing the issue again.

问题

我们所看到的是在一段时间内一切都会正常运行,然后在几个小时后,问题再次出现。

What we're seeing is that everything will work fine for some time, and then after several hours, the issue will emerge again.

我们有一种解决方法,可以还原服务-即在azure控制面板中启用然后禁用应用程序服务身份验证。相反的方法也一样-禁用然后启用将还原服务。

We have a work around fix to restore service - that is to enable and then disable app service authentication in the azure control panel. The opposite works too - to disable and then enable will restore service.

代码

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相关的问题-因为这是在会话之间转移状态的唯一方法。这到底是什么问题?以及我需要采取哪些步骤来诊断和解决问题?

So, based on whatever enabling and disabling app-service authentication does, it's clearly fixing thing temporarily. So I'm thinking this is a cookie related problem - as that'd be the only thing transferring state between sessions. What on earth could be the issue here? And what steps do I need to take to diagnose and resolve the issue?

推荐答案

到目前为止,这似乎是一个问题与Katana中的一个已知错误有关,该错误中Katana cookie管理器和ASP .NET cookie管理器发生冲突并覆盖彼此的cookie。

So far, it seems like it was a problem with a known bug in Katana where the Katana cookie manager and the ASP .NET cookie manager clash and overwrite each other's cookies.

以下是一些故障排除方法,您可以参考:

Here are some troubleshoots you could refer to:

1。设置
app.UseCookieAuthentication(新的CookieAuthenticationOptions {CookieSecure == CookieSecureOption.Always})

2。在中添加 SystemWebCookieManager Microsoft.Owin.Host.SystemWeb Nuget包中的UseCookieAuthentication 。请参考此。

2.Add SystemWebCookieManager in UseCookieAuthentication which is in the Microsoft.Owin.Host.SystemWeb Nuget package. Please refer to this thread.

3. 。有人注意到,如果Cookie字符超过浏览器限制(> 4096),就会出现问题。因此,要解决该问题,请在每个cookie中包含大约4000个字符,并在需要时将所有cookie组合在一起以获得原始值。

3.Split cookie. Someone noticed that it was issue if Cookie characters are more than browsers limit (> 4096). So to overcome that issue, in set-cookie with around 4000 characters with each and when needed combine all cookie together to get original value.

有关如何添加的更多详细信息使用Microsoft登录到ASP.NET Web应用程序,请参阅此。

For more details about how to add sign-in with Microsoft to an ASP.NET web app, please refer to this article.

更新

使用安装 Kentor.OwinCookieSaver nuget包修复并添加 app.UseKentorOwinCookieSaver() ; app.UseCookieAuthentication(new CookieAuthenticationOptions())之前;

Fix with install Kentor.OwinCookieSaver nuget package and add app.UseKentorOwinCookieSaver(); before app.UseCookieAuthentication(new CookieAuthenticationOptions());

这篇关于Azure应用服务上的瞬态无限登录循环-使用Azure AD的OpenIDConnect Auth的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 18:44