.NET BFF集成Azure AD+OpenIDConnect认证后重定向循环问题
场景说明
需实现作为Angular SPA的BFF的Web API,通过Azure Active Directory处理用户认证,后端存储Bearer令牌和刷新令牌。Azure端配置已完成,重定向URL为https://localhost/signin-oidc,使用Duende.AccessTokenManagement和Duende.AccessTokenManagement.OpenIdConnect NuGet包实现自动令牌管理。
应用配置代码
var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; options.DefaultSignOutScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(options => { options.ExpireTimeSpan = TimeSpan.FromHours(1); options.SlidingExpiration = false; options.Cookie.SameSite = SameSiteMode.Strict; options.Cookie.Name = "__Host-ui"; options.Events.OnSigningOut = async e => { await e.HttpContext.RevokeRefreshTokenAsync(); }; }) .AddOpenIdConnect(options => { options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.Authority = "https://login.microsoftonline.com/{tenantId}/v2.0"; options.ClientId = "clientId from config"; options.ClientSecret = "secret from config"; options.UsePkce = true; options.ResponseType = OpenIdConnectResponseType.Code; options.ResponseMode = OpenIdConnectResponseMode.Query; options.Scope.Clear(); options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.Scope.Add("offline_access"); options.Scope.Add("api"); options.Scope.Add("name"); options.Scope.Add("ipaddr"); options.GetClaimsFromUserInfoEndpoint = true; options.SaveTokens = true; options.MapInboundClaims = false; options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always; options.NonceCookie.SecurePolicy = CookieSecurePolicy.Always; options.RequireHttpsMetadata = false; }); builder.Services.AddOpenIdConnectAccessTokenManagement(); builder.Services.AddControllers(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
控制器代码
[ApiController] public class AuthenticationController : ControllerBase { [HttpGet("hello")] [Authorize] public IActionResult Hello() { return new JsonResult("Hello"); } }
问题现象
访问hello接口时,认证中间件自动重定向到Microsoft登录页面,登录成功获取令牌后,出现https://localhost/signin-oidc与hello接口之间的无限循环,几次请求后报错:
Correlation failed
解决方案
修正SameSite Cookie设置:当前
SameSiteMode.Strict可能导致跨站场景下Cookie无法正确携带,BFF架构开发阶段建议改为SameSiteMode.Lax测试:options.Cookie.SameSite = SameSiteMode.Lax;调整Correlation Cookie安全策略:
CookieSecurePolicy.Always要求必须在HTTPS环境下,若开发环境使用自签名证书未被浏览器信任,Cookie无法正常存储读取,可临时改为:options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.NonceCookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;验证回调路由处理:确保OpenID Connect的
/signin-oidc回调路径被认证中间件正确处理,检查中间件顺序(UseAuthentication()需在UseAuthorization()前),无需额外映射该路由,但要保证应用能接收回调请求。检查令牌存储与事件:添加
OnTokenValidated事件验证令牌是否正确保存,排查令牌管理流程问题:options.Events.OnTokenValidated = async context => { var refreshToken = context.Properties.GetTokenValue("refresh_token"); // 用ILogger记录refreshToken是否存在,确认令牌获取正常 await Task.CompletedTask; };核对Azure AD应用配置:确保Azure AD应用注册中的重定向URI完全匹配
https://localhost/signin-oidc,应用类型设置为Web,且Authorization Code Flow配置正确。
内容的提问来源于stack exchange,提问作者pospich0815

