使用Blazor InteractiveAuto与Microsoft Entra时GraphQL认证调用失败
Blazor InteractiveAuto模式下GraphQL授权问题修复方案
问题复盘
在Blazor InteractiveAuto模式下配置服务器端GraphQL客户端,未添加授权时功能正常,但启用必填授权后,系统未使用已存在的.AspNetCore.Cookies进行认证,反而触发OIDC重定向;更异常的是,端点返回404而非预期的400未授权状态。已通过Nitro工具验证:登录状态下无需额外配置即可访问认证端点(工具会自动传递Cookie),但注销状态下同样收到404。
核心问题
- 默认认证方案为OIDC,即使GraphQL端点指定Cookie方案,中间件仍优先触发OIDC的重定向逻辑
- 手动创建的
CookieContainer是全新实例,未复用当前用户的认证Cookie,导致请求无有效凭证 - GraphQL端点路由或授权配置模糊,引发404路由匹配错误
分步修复
1. 调整认证方案默认配置
将Cookie设为默认认证方案,同时保留OIDC用于登录流程:
// 注册认证服务,设置Cookie为默认方案 builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie() .AddMicrosoftIdentityWebApp( builder.Configuration.GetSection("AzureAd"), openIdConnectScheme: OpenIdConnectDefaults.AuthenticationScheme, cookieScheme: CookieAuthenticationDefaults.AuthenticationScheme);
2. 让GraphQL客户端复用当前请求的Cookie
手动创建的CookieContainer不会包含用户的认证Cookie,需要从当前HttpContext中获取并复用:
// 先注册HttpContextAccessor builder.Services.AddHttpContextAccessor(); // 配置GraphQL客户端 builder.Services.AddScoped(sp => { var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>(); var navigationManager = sp.GetRequiredService<NavigationManager>(); var baseUri = new Uri(navigationManager.BaseUri); var handler = new HttpClientHandler { UseCookies = true, CookieContainer = httpContextAccessor.HttpContext?.Request.Cookies.ToCookieContainer(baseUri) }; return new GraphQLHttpClient(config => { config.EndPoint = new Uri($"{navigationManager.BaseUri}graphql"); config.HttpMessageHandler = handler; }, new SystemTextJsonSerializer()); }); // 扩展方法:将RequestCookies转换为CookieContainer public static CookieContainer ToCookieContainer(this IRequestCookieCollection cookies, Uri baseUri) { var container = new CookieContainer(); if (cookies == null) return container; foreach (var cookie in cookies) { container.Add(new Cookie(cookie.Key, cookie.Value, "/", baseUri.Host)); } return container; }
3. 修正GraphQL端点的授权与路由配置
明确指定GraphQL路径,并创建专属授权策略,避免路由模糊匹配导致404:
// 配置GraphQL端点,指定路径并绑定专属授权策略 app.MapGraphQL("/graphql") .RequireAuthorization(options => { options.AddPolicy("GraphQLCookieAuth", policy => { policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); }); });
4. 禁用API请求的OIDC自动重定向
对GraphQL这类API请求,直接返回401而非重定向到登录页:
.AddMicrosoftIdentityWebApp( builder.Configuration.GetSection("AzureAd"), openIdConnectScheme: OpenIdConnectDefaults.AuthenticationScheme, cookieScheme: CookieAuthenticationDefaults.AuthenticationScheme) .AddOpenIdConnect(options => { options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = context => { // 拦截GraphQL请求,返回401而非重定向 if (context.Request.Path.StartsWithSegments("/graphql")) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; context.HandleResponse(); } return Task.CompletedTask; } }; });
验证步骤
- 登录后检查浏览器网络请求,确认GraphQL请求头包含
.AspNetCore.CookiesCookie - 注销状态下访问GraphQL端点,应返回401而非404
- 用Nitro工具再次测试,确保端点路由与授权逻辑正常
内容的提问来源于stack exchange,提问作者Evan Kaiser
相关产品推荐
相关产品推荐

