Azure AD 同时登录不同应用程序后用户未经授权

Posted

技术标签:

【中文标题】Azure AD 同时登录不同应用程序后用户未经授权【英文标题】:User unauthorized after Azure AD login to different application simultaneously 【发布时间】:2021-12-31 07:26:45 【问题描述】:

我有两个 MVC 应用程序 AppA 和 AppB,并为登录实现了 Azure AD 身份验证。 我能够成功登录这两个应用程序。 但问题是,在我登录到 AppA 然后再登录到 AppB 之后,当我返回 AppA 时,我面临用户已注销的问题,并且它再次重定向到登录屏幕(在 AppA 中)。 在我登录到 AppA(第二次)并返回到 AppB 后(AppB 中的用户已注销)。

客户端 ID 不同; TenandID 相同。两个应用都托管在同一台服务器上。

启动文件:

public void ConfigureAuth(IAppBuilder app)
        
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                SlidingExpiration = true,
                Provider = new CookieAuthenticationProvider
                
                    OnResponseSignIn = context =>
                    
                        context.Properties.AllowRefresh = true;
                        context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1);
                    ,
                    OnValidateIdentity = MyCookieValidateIdentity
                ,
                ExpireTimeSpan = TimeSpan.FromDays(2)
            );

            app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            
                ClientId = appId,
                //CookieManager=new SameSiteCookieManager(new SystemWebCookieManager()),
                Authority = "https://login.microsoftonline.com/xxxxxx/v2.0",
                Scope = $"openid email profile offline_access graphScopes",
                RedirectUri = redirectUri,
                PostLogoutRedirectUri = redirectUri,
                TokenValidationParameters = new TokenValidationParameters
                
                    ValidateIssuer = true,
                ,
                Notifications = new OpenIdConnectAuthenticationNotifications
                
                    RedirectToIdentityProvider = (context) =>
                    
                        context.ProtocolMessage.DomainHint = "xyz.com";
                        return Task.FromResult(0);
                    ,
                    // SecurityTokenValidated = OnSecurityTokenValidated,
                    AuthenticationFailed = OnAuthenticationFailedAsync,
                    AuthorizationCodeReceived = OnAuthorizationCodeReceivedAsync
                
            
            );
        

actionContext.RequestContext.Principal.Identity.IsAuthenticated 正在返回 False

我假设它必须对 cookie 做一些事情。有人可以帮忙解决这个问题吗?

编辑: 进一步调试发现: 最初,如果 AppA 的 cookie 设置为: .AspNet.Cookies = A_abc123 ; ASP.NET_SessionId = A_def456 对于 AppB .AspNet.Cookies = B_mno123 ; ASP.NET_SessionId = B_pqr456 然后在我单击 AppA 中的任何链接后,cookie 的值将使用 AppB 的 cookie 进行更新,即 .AspNet.Cookies = B_mno123 ; ASP.NET_SessionId = B_pqr456

      .AspNet.Cookies   ASP.NET_SessionId 
AppA  A_abc123          A_def456
AppB  B_mno123          B_pqr456
AppA  B_mno123          B_pqr456

【问题讨论】:

【参考方案1】:

您需要做的一件事是配置数据保护 API,以便两个服务使用相同的 cookie 保护密钥。开箱即用的每个服务都会创建自己的唯一密钥,并且来自一个服务的 cookie 在不同的服务中无效。

我还写了一篇关于数据保护 API here 的博文。

How to: Use Data Protection Get started with the Data Protection APIs in ASP.NET Core

【讨论】:

感谢 Tore,这看起来很有希望,但我正在寻找更方便的代码更改更少的东西,主要是在 Startup.cs 文件中。 您可以在 startup.cs 中完成大部分工作/更改,但您仍然需要在外部存储数据保护 API 密钥(密钥环)。 感谢 Tore,我发现问题出在 Cookie 上,因此通过重命名 cookie,问题得到了解决。【参考方案2】:
 public void ConfigureAuth(IAppBuilder app)
 
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            
                //AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,// DefaultAuthenticationTypes.ApplicationCookie,
                CookieName = ".AspNet.AppA.Cookies",
                SlidingExpiration = true,
                CookieManager = new SystemWebCookieManager(),
                Provider = new CookieAuthenticationProvider
                
                    OnResponseSignIn = context =>
                    
                        context.Properties.AllowRefresh = true;
                        context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1);
                    ,
                ,
               ExpireTimeSpan = TimeSpan.FromDays(2)
            );
            //... code removed for brevity //

应用程序设置的默认 Cookie 名称为:.AspNet.Cookies 当我修改默认 cookie 名称时,问题得到了解决。每个应用程序都在生成自己的 cookie 名称,因此其他应用程序没有退出用户。

【讨论】:

以上是关于Azure AD 同时登录不同应用程序后用户未经授权的主要内容,如果未能解决你的问题,请参考以下文章

Azure AD B2C 图形 API 401 未经授权

如何在 ASP.NET Core 3 上同时使用 Azure AD 身份验证和身份?

Azure AD:访问令牌中缺少角色声明

使用Azure AD时的VueJS用户权限

Azure AD 与 AWS IAM 集成实现SSO—上(Azure部分)

Azure AD 链接帐户和备用登录映射