【问题标题】:GraphQL authentication with Asp.net core using JWT使用 JWT 与 Asp.net 核心进行 GraphQL 身份验证
【发布时间】:2018-11-10 17:05:28
【问题描述】:

我正在为 graphql 使用 GraphQL for .NET 包。但我不明白如何在 graphql 查询或突变中使用 JWT 进行身份验证。

我阅读了guide about authorization,但我无法完成。

我需要 GraphQL 方面的帮助以进行 .NET 身份验证。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 不确定我是否理解两者的关系。使用 JWT,您可以针对您的应用对用户进行身份验证。当他点击控制器操作时,用户已经填充了声明并且可以与您链接的示例一起使用?
  • 但是我们应该使用 JWT 有效负载授权 graphql 查询吗?
  • 乍一看(没有看细节)链接的例子只分别使用了IPrincipal/ClaimsPrincipal。您所做的就是检查用户是否有特定的声明(在此示例中)。在请求过程中较早填充的声明。阅读,您将声明发送到您的 API,该 API 使用声明和所有其他信息填充用户属性。此时您无需担心用户是否通过 jwt、cookie 或其他方式进行身份验证
  • 好的,我明白了。谢谢。但在同一指南中,它显示了实施。但它有很多错误。我需要这个吗?这里实现:github.com/graphql-dotnet/authorization

标签: authentication asp.net-core graphql graphql-dotnet


【解决方案1】:

指南是关于授权的。您正在寻找的步骤是身份验证,由于 graphql 可以使用 ASP.Net API 控制器实现,因此您可以像使用任何控制器一样实现 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 不记名令牌身份验证。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我自己也挣扎了两天。我现在正在使用https://github.com/graphql-dotnet/authorization 与此评论中的设置(来自我):https://github.com/graphql-dotnet/authorization/issues/63#issuecomment-553877731

    简而言之,您必须正确设置UserContextAuthorizationValidationRule,如下所示:

    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; }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-05-13
      • 2018-03-17
      • 2018-08-31
      • 2017-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 2016-04-07
      相关资源
      最近更新 更多