You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:57:13