我正在使用GraphQL for .NET包的 graphql。但我不明白如何在 graphql 查询或突变中使用 JWT 进行身份验证。
我阅读了有关授权的指南,但我无法完成。
我需要 GraphQL 方面的帮助以进行 .NET 身份验证。
任何帮助将不胜感激。
谢谢
我正在使用GraphQL for .NET包的 graphql。但我不明白如何在 graphql 查询或突变中使用 JWT 进行身份验证。
我阅读了有关授权的指南,但我无法完成。
我需要 GraphQL 方面的帮助以进行 .NET 身份验证。
任何帮助将不胜感激。
谢谢
该指南围绕授权。您正在寻找的步骤是身份验证,并且由于可以使用 ASP.Net API 控制器实现 graphql,因此您可以像使用任何控制器一样实现 JWT 身份验证。
这是一个使用 Authorize 属性的示例 grapql 控制器。但是,您可以使用过滤器来实现这一点,或者如果您想要完全控制,自定义中间件。
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class GraphQLController : ControllerBase
{
private readonly IDocumentExecuter executer;
private readonly ISchema schema;
public GraphQLController(IDocumentExecuter executer, ISchema schema)
{
this.executer = executer;
this.schema = schema;
}
[HttpPost]
public async Task<ActionResult<object>> PostAsync([FromBody]GraphQLQuery query)
{
var inputs = query.Variables.ToInputs();
var queryToExecute = query.Query;
var result = await executer.ExecuteAsync(o => {
o.Schema = schema;
o.Query = queryToExecute;
o.OperationName = query.OperationName;
o.Inputs = inputs;
o.ComplexityConfiguration = new GraphQL.Validation.Complexity.ComplexityConfiguration { MaxDepth = 15};
o.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
}).ConfigureAwait(false);
return this.Ok(result);
}
}
public class GraphQLQuery
{
public string OperationName { get; set; }
public string Query { get; set; }
public Newtonsoft.Json.Linq.JObject Variables { get; set; }
}
在 Startup.cs 中,我配置了 JWT 不记名令牌身份验证。
希望这可以帮助。
我自己也挣扎了两天。我现在正在使用https://github.com/graphql-dotnet/authorization以及来自此评论的设置(来自我):https ://github.com/graphql-dotnet/authorization/issues/63#issuecomment-553877731
简而言之,您必须正确设置UserContext
for AuthorizationValidationRule
,如下所示:
public class Startup
{
public virtual void ConfigureServices(IServiceCollection services)
{
...
services.AddGraphQLAuth(_ =>
{
_.AddPolicy("AdminPolicy", p => p.RequireClaim("Role", "Admin"));
});
services.AddScoped<IDependencyResolver>(x => new FuncDependencyResolver(x.GetRequiredService));
services.AddScoped<MySchema>();
services
.AddGraphQL(options => { options.ExposeExceptions = true; })
.AddGraphTypes(ServiceLifetime.Scoped);
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
...
app.UseMiddleware<MapRolesForGraphQLMiddleware>(); // optional, only when you don't have a "Role" claim in your token
app.UseGraphQL<MySchema>();
...
}
}
public static class GraphQLAuthExtensions
{
public static void AddGraphQLAuth(this IServiceCollection services, Action<AuthorizationSettings> configure)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthorizationEvaluator, AuthorizationEvaluator>();
services.AddTransient<IValidationRule, AuthorizationValidationRule>();
services.AddTransient<IUserContextBuilder>(s => new UserContextBuilder<GraphQLUserContext>(context =>
{
var userContext = new GraphQLUserContext
{
User = context.User
};
return Task.FromResult(userContext);
}));
services.AddSingleton(s =>
{
var authSettings = new AuthorizationSettings();
configure(authSettings);
return authSettings;
});
}
}
public class GraphQLUserContext : IProvideClaimsPrincipal
{
public ClaimsPrincipal User { get; set; }
}
public class MapRolesForGraphQLMiddleware
{
private readonly RequestDelegate _next;
public MapRolesForGraphQLMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// custom mapping code to end up with a "Role" claim
var metadata = context.User.Claims.SingleOrDefault(x => x.Type.Equals("metadata"));
if (metadata != null)
{
var roleContainer = JsonConvert.DeserializeObject<RoleContainer>(metadata.Value);
(context.User.Identity as ClaimsIdentity).AddClaim(new Claim("Role", string.Join(", ", roleContainer.Roles)));
}
await _next(context);
}
}
public class RoleContainer
{
public String[] Roles { get; set; }
}