配置Kestrel GraphQL用户认证 解决Playground 401访问问题
问题描述
已创建并配置GraphQL服务器与Playground,当前/graphql端点已启用认证要求,但打开Playground时提示无法访问schema(访问被拒绝),报错信息为:
"error": "Response not successful: Received status code 401"
直接访问/graphql端点同样会被拒绝,浏览器未触发用户认证流程。需要配置/playground实现用户认证,并携带token调用/graphql接口。
现有代码
WebApplication构建代码
var builder = WebApplication.CreateBuilder(args); builder.Services.AddHealthChecks(); Settings.AppSettings = builder.Configuration; builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(builder.Configuration.GetRequiredSection("AzureAd")); builder.Services.AddSingleton<AnyScalarGraphType>(); builder.Services.AddSingleton<ServiceGraphType>(); builder.Services.AddTransient<Query>(); builder.Services.AddTransient<Mutation>(); builder.Services.AddTransient<ISchema>(s => DocumentSchema.CreateSchema()); builder.Services.AddGraphQL(b => b .AddErrorInfoProvider(opt => opt.ExposeExceptionDetails = true) .AddUserContextBuilder(new Func<HttpContext, Dictionary<string, object?>>(httpContext => new RuntimeContext(httpContext))) .AddSystemTextJson() ); builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter()); }); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.MapHealthChecks("/health"); app.UseGraphQL("/graphql", config => { config.AuthorizationRequired = true; }); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseGraphQLPlayground( "/playground", new GraphQL.Server.Ui.Playground.PlaygroundOptions { GraphQLEndPoint = "/graphql", RequestCredentials = GraphQL.Server.Ui.Playground.RequestCredentials.Include } ); } await app.RunAsync();
appsettings.json配置
{ "Logging": { "LogLevel": { "Default": "Warning", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "Kestrel": { "Endpoints": { "Https": { "Url": "https://+:4002" } } } }
解决方案
1. 补全Azure AD配置
当前appsettings.json缺少Azure AD的核心配置,需添加以下节点(替换为你的实际Azure AD信息):
"AzureAd": { "Instance": "https://login.microsoftonline.com/", "TenantId": "你的租户ID", "ClientId": "你的应用客户端ID", "Audience": "你的API受众(通常是客户端ID或自定义URI)" }
2. 配置Playground支持OAuth2授权
修改PlaygroundOptions,添加OAuth配置,让Playground自动触发认证流程并获取token:
app.UseGraphQLPlayground( "/playground", new GraphQL.Server.Ui.Playground.PlaygroundOptions { GraphQLEndPoint = "/graphql", RequestCredentials = GraphQL.Server.Ui.Playground.RequestCredentials.Include, OAuth = new GraphQL.Server.Ui.Playground.OAuthSettings { ClientId = "你的应用客户端ID", ClientSecret = "你的应用客户端密钥(如果需要)", AuthorizationUrl = "https://login.microsoftonline.com/你的租户ID/oauth2/v2.0/authorize", TokenUrl = "https://login.microsoftonline.com/你的租户ID/oauth2/v2.0/token", Scopes = new[] { "你的API受众/access_as_user" } // 替换为你的API权限范围 } } );
3. 验证认证中间件顺序
确保app.UseAuthentication()和app.UseAuthorization()在app.UseGraphQL()之前执行,当前代码顺序正确,无需调整。
4. 手动设置Authorization头(临时方案)
如果OAuth配置暂时无法生效,可在Playground的"HTTP HEADERS"面板手动添加JWT token:
{ "Authorization": "Bearer 你的JWT Token" }
5. 配置CORS(跨域场景)
如果Playground与GraphQL端点存在跨域访问,需添加CORS支持:
// 在builder.Services.AddGraphQL之前添加 builder.Services.AddCors(options => { options.AddPolicy("AllowPlayground", policy => { policy.WithOrigins("https://localhost:4002") // 你的Playground地址 .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); // 在app.UseAuthentication()之后添加 app.UseCors("AllowPlayground");
内容的提问来源于stack exchange,提问作者igorjrr
相关产品推荐
相关产品推荐

