Azure AD登录关联失败排查及用户登录数据获取咨询
问题描述
我尝试通过HTTP协议对接Azure AD实现登录并获取已登录用户的数据,但在配置应用认证后出现错误:Exception: An error was encountered while handling the remote login. Correlation failed。以下是Startup中的配置服务及中间件代码:
services.AddDistributedMemoryCache(); services.AddSession(options => { options.Cookie.Name = "data"; // Set your session cookie name options.IdleTimeout = TimeSpan.FromMinutes(30); // Set session timeout options.Cookie.IsEssential = true; // Essential for authentication }); // Cookie Authentication and OpenID Connect setup (if needed) services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(options => { options.Cookie.Name = "AuthCookie"; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.SlidingExpiration = true; options.Cookie.SameSite = SameSiteMode.Lax; }) .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { options.Authority = "https://login.microsoftonline.com/****************/"; options.ClientId = "**************"; options.ClientSecret = "******************"; options.ResponseType = "code"; options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.CallbackPath = "/en/masterbom"; options.SaveTokens = true; options.Events.OnTicketReceived = async context => { var claimsIdentity = context.Principal.Identity as ClaimsIdentity; if (claimsIdentity != null) { // Modify or add claims if needed } }; }); public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionHandler(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseSession(); app.UseAuthentication(); }
请问如何修复该错误并获取已登录用户的数据?
一、解决"Correlation failed"错误
该错误多由中间件顺序错误、重定向URI不匹配、Cookie配置冲突导致,按以下步骤修复:
1. 修正中间件执行顺序
Configure方法必须添加UseAuthorization,且严格遵循中间件执行顺序:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); // 生产环境建议启用HTSTS } app.UseStaticFiles(); app.UseRouting(); app.UseSession(); app.UseAuthentication(); app.UseAuthorization(); // 必须添加,且位于UseAuthentication之后 // 添加端点路由配置(MVC/Razor Pages必备) app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
2. 匹配Azure AD重定向URI
登录Azure Portal,找到你的应用注册,在认证页面的"重定向URI"中,添加与代码中options.CallbackPath完全一致的地址。例如代码中是/en/masterbom,则添加http://localhost:5000/en/masterbom(开发环境)或生产环境的对应HTTPS地址。
3. 调整OIDC关联Cookie配置
在AddOpenIdConnect中补充关联Cookie的配置,避免同站/跨域问题:
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { // 保留原有配置... // 配置关联Cookie options.CorrelationCookie.SameSite = SameSiteMode.Lax; options.CorrelationCookie.HttpOnly = true; // 开发环境HTTP下允许非安全Cookie(生产必须用HTTPS,设为SameAsRequest) if (env.IsDevelopment()) { options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.None; } })
4. 移除不必要的Session配置(可选)
OIDC本身会处理关联逻辑,若业务不需要Session,可移除AddDistributedMemoryCache()和AddSession()相关代码,避免Cookie冲突。
二、获取已登录用户数据
1. 通过ClaimsPrincipal直接获取基础信息
在控制器中,使用User属性访问用户的声明信息:
public IActionResult UserProfile() { // 获取Azure AD对象ID(用户唯一标识) var userId = User.FindFirstValue("oid"); // 获取用户名 var userName = User.FindFirstValue(ClaimTypes.Name); // 获取邮箱 var email = User.FindFirstValue(ClaimTypes.Email); // 获取用户名字 var givenName = User.FindFirstValue(ClaimTypes.GivenName); // 可将数据传递给视图或业务逻辑 return View(new { UserId = userId, UserName = userName, Email = email }); }
2. 在OnTicketReceived事件中扩展用户数据
利用已有的OnTicketReceived事件,可添加自定义声明或调用Microsoft Graph API获取更多用户信息:
options.Events.OnTicketReceived = async context => { var claimsIdentity = context.Principal.Identity as ClaimsIdentity; if (claimsIdentity != null) { // 添加自定义声明 var tenantId = context.Principal.FindFirstValue("tid"); claimsIdentity.AddClaim(new Claim("TenantId", tenantId)); // 调用Microsoft Graph API获取详细用户数据(需添加Graph SDK依赖) var accessToken = await context.HttpContext.GetTokenAsync("access_token"); // var graphClient = new GraphServiceClient( // new DelegateAuthenticationProvider(req => // { // req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); // return Task.CompletedTask; // })); // var userDetails = await graphClient.Me.Request().GetAsync(); // 可将Graph返回的信息添加为声明 } };
3. 在Razor视图中展示用户数据
直接在视图中使用User对象读取信息:
<div class="user-info"> <p>当前登录用户:@User.Identity.Name</p> <p>邮箱:@User.FindFirstValue(ClaimTypes.Email)</p> <p>租户ID:@User.FindFirstValue("tid")</p> </div>
额外排查建议
- 开发环境使用HTTP时,确保Azure AD应用注册允许HTTP重定向URI(生产环境强制HTTPS)。
- 开启调试日志排查细节:在
appsettings.json中添加日志配置,查看认证过程的详细错误:
{ "Logging": { "LogLevel": { "Microsoft.AspNetCore.Authentication": "Debug", "Microsoft.AspNetCore.Authentication.OpenIdConnect": "Debug" } } }
内容的提问来源于stack exchange,提问作者Moheman Aldulimy

