Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to extract claims from a token and add to policy. #33

Closed
RaySheikh opened this issue Dec 22, 2018 · 7 comments
Closed

How to extract claims from a token and add to policy. #33

RaySheikh opened this issue Dec 22, 2018 · 7 comments
Labels
question Further information is requested

Comments

@RaySheikh
Copy link

Hi, I am currently using a ClaimsTransformer class which inherits from IClaimsTransformation and injects custom claims (users/roles) from my db based on the user name i receive from the jwt token. What is the best way to use these custom claims to build a policy?

Thanks!

@matthewevans87
Copy link

I believe I am experiencing a similar roadblock.

Startup.cs

            services.AddGraphQLAuth(options => {
                options.AddPolicy("AdminPolicy", p => {
                    p.RequireClaim(ClaimTypes.Role, "admin");
                });
            });

            services.AddGraphQL(options =>
            {
                options.EnableMetrics = true;
                options.ExposeExceptions = true;
            })
            .AddUserContextBuilder(httpContext =>
            {
                return new GraphQLUserContext { User = httpContext.User };
            });

            services.AddMvc();

setting a breakpoint on return new GraphQLUserContext { User = httpContext.User }; reveals that my custom claim has been added (via middleware), yet GraphiQL reports the error
"message": "GraphQL.Validation.ValidationError: You are not authorized to run this query.\nRequired claim 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' with any value of 'admin' is not present.",

@tulde23
Copy link

tulde23 commented Jan 30, 2019

You could always create your own IAuthorizationEvaluator and register it with the IOC container.

public class JwtTokenAuthorizationEvaluator : IAuthorizationEvaluator
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IHostingEnvironment _environment;
        private readonly AuthorizationSettings _authorizationSettings;

        public JwtTokenAuthorizationEvaluator(IHttpContextAccessor httpContextAccessor, 
            IHostingEnvironment environment, 
            AuthorizationSettings authorizationSettings)
        {
            _httpContextAccessor = httpContextAccessor;
            _environment = environment;
            _authorizationSettings = authorizationSettings;
        }

        public async Task<AuthorizationResult> Evaluate(ClaimsPrincipal principal, object userContext, Dictionary<string, object> arguments, IEnumerable<string> requiredPolicies)
        {
            var cxt = userContext as GraphQLUserContext;
            ClaimsPrincipal claimsPrincipal = _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated ? _httpContextAccessor.HttpContext.User : null;
            if (claimsPrincipal == null)
            {
                var response = await _httpContextAccessor.HttpContext.AuthenticateAsync();
                if (response.Succeeded)
                {
                    claimsPrincipal = response.Principal;
                    _httpContextAccessor.HttpContext.User = response.Principal;
                }
                else
                {
                    return AuthorizationResult.Fail(SuperEnumerable.Produce(response.Failure.Message));
                }
            }

            var context = new AuthorizationContext();
            context.User = claimsPrincipal;
            context.UserContext = userContext;
            context.Arguments = arguments;

            var authPolicies = _authorizationSettings.GetPolicies(requiredPolicies);
            var tasks = new List<Task>();
            authPolicies.Apply(p =>
            {
                p.Requirements.Apply(r =>
                {
                    var task = r.Authorize(context);
                    tasks.Add(task);
                });
            });

            await Task.WhenAll(tasks.ToArray());
            return !context.HasErrors
            ? AuthorizationResult.Success()
            : AuthorizationResult.Fail(context.Errors);
        }

@BKB503
Copy link

BKB503 commented Mar 20, 2019

@tulde23 do you have any example with JWT bearer auth? for authorize and anonymous request with different graphql queries

@tulde23
Copy link

tulde23 commented Mar 20, 2019

 /// <summary>
    /// Defines a GraphQL user context.
    /// </summary>
    [ExcludeFromCodeCoverage]
    public class GraphQLUserContext : IProvideClaimsPrincipal
    {
        /// <summary>
        /// Gets or sets the user.
        /// </summary>
        /// <value>
        /// The user.
        /// </value>
        public ClaimsPrincipal User { get; set; }
    }

public static void AddAuthorization( this IServiceCollection services){
   .AddUserContextBuilder(httpContext =>
                {
                    if (httpContext.User.Identity.IsAuthenticated)
                    {
                        return new GraphQLUserContext { User = httpContext.User };
                    }
                    else
                    {
                        var result = httpContext.AuthenticateAsync().GetAwaiter().GetResult();
                        if (result.Succeeded)
                        {
                            httpContext.User = result.Principal;
                        }
                        return new GraphQLUserContext { User = result.Principal };
                    }
                });


  /// <summary>
    /// Sets a default level of security for all types.
    /// </summary>
    /// <typeparam name="TSourceType">The type of the source type.</typeparam>
    [ExcludeFromCodeCoverage]
    public class SecureObjectGraphType<TSourceType> : ObjectGraphType<TSourceType>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SecureObjectGraphType{TSourceType}"/> class.
        /// </summary>
        public SecureObjectGraphType()
        {
            this.AuthorizeWith("DefaultPolicy");
        }
    }
/// 
 [ExcludeFromCodeCoverage]
    public class MyGraphQLType : SecureObjectGraphType<GraphQLEntity>
    {
           public MyGraphQLType(){
//you can only access this field if you are have "MyPolicy".  
   Field(x => x.SecureField, true).AuthorizeWith("MyPolicy");
Field(x => x.Name, true))
}
     }
}

@BKB503
Copy link

BKB503 commented Mar 20, 2019

@tulde23 Thank you, I have used the JwtTokenAuthorizationEvaluator and it is handing the authenticated and anonymous graphql queries as well

@OpenSpacesAndPlaces
Copy link

Very similarly to the above approach, you can also use:
IAuthorizationRequirement

#49 (comment)

@sungam3r sungam3r added the question Further information is requested label May 19, 2020
@sungam3r
Copy link
Member

Closed as outdated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants