-
Notifications
You must be signed in to change notification settings - Fork 163
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
.net core 7 AddAuthorizationRule not work #993
Comments
Can you post a list of the GraphQL nuget packages you have installed ? |
Thanks for you. |
IMS_Schemas:
|
I tested the code you provided and it seems to work for me. See PR #994 -- all tests pass, both successful and access-denied tests for the modified sample project:
Can you paste the Can you verify that your Can you verify that you are not referencing any other GraphQL nuget packages? |
app.UseGraphQL<IMS_Schemas>("/IMS_Schemas/graphql"); [Authorize] attribute references GraphQL.GraphQLAttribute Thank for you. |
|
Program.cs: using GraphQL; var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthorization(options => builder.Services.AddTransient<IAuthorizationHandler, MinimumAgeHandler>(); builder.Services.AddRazorPages(); builder.Services.AddGraphQL(b => b
//builder.Services.AddRouting(); //builder.Services.AddCors(options => options.AddPolicy("all", p => p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader())); var app = builder.Build(); app.UseDeveloperExceptionPage(); app.UseAuthentication(); app.UseWebSockets(); //app.UseRouting(); //app.UseCors("all"); // configure the graphql endpoint at "/Common_Base_Schemas/graphql" // configure Playground at "/Common_Base_Schemas/ui/playground" with relative link to api // configure the graphql endpoint at "/IMS_Schemas/graphql" // configure Playground at "/IMS_Schemas/ui/playground" with relative link to api app.MapRazorPages(); |
Query.cs: using GraphQL; namespace KDRun.Model.GraphType.IMS
} |
I just realized what the issue is. Your authorization policy does not require the user to be authenticated, as it always returns And here: And here: And here: And here: This was implemented as an optimization so that policies need not be checked if the user is not authenticated in the first place. This may differ from ASP.NET Core's logic. We can consider changing this in a future version of GraphQL.NET if you can provide reasoning why this should not be the case. To change behavior in the current version of GraphQL.NET, you would need to:
|
Another option is to use the authorization project. There are some limitations, such as |
Another option would be to derive from |
Here is a sample of the latter: public class MyAuthorizationVisitor : AuthorizationVisitor
{
public MyAuthorizationVisitor(ValidationContext context, ClaimsPrincipal claimsPrincipal, IAuthorizationService authorizationService)
: base(context, claimsPrincipal, authorizationService)
{
}
protected override bool IsAuthenticated => true;
}
public class MyAuthorizationRule : IValidationRule
{
public virtual async ValueTask<INodeVisitor?> ValidateAsync(ValidationContext context)
{
var user = context.User
?? throw new InvalidOperationException("User could not be retrieved from ValidationContext. Please be sure it is set in ExecutionOptions.User.");
var provider = context.RequestServices
?? throw new MissingRequestServicesException();
var authService = provider.GetService<IAuthorizationService>()
?? throw new InvalidOperationException("An instance of IAuthorizationService could not be pulled from the dependency injection framework.");
var visitor = new MyAuthorizationVisitor(context, user, authService);
// if the schema fails authentication, report the error and do not perform any additional authorization checks.
return await visitor.ValidateSchemaAsync(context) ? visitor : null;
}
}
builder.AddValidationRule<MyAuthorizationRule>();
// remove builder.AddAuthorizationRule() |
Thank you for your reply. In our plan, the authentication framework of .net core is not used. We customize the authentication process and combine it with radis cluster. When the user accesses a specific method, we use the custom authentication to check, that it is legal Let it go, and we will terminate the access if it is illegal. |
Then perhaps you would just take the sample above, and instead of deriving from |
Sample of the latter: public class MyAuthorizationVisitor : AuthorizationVisitorBase
{
public MyAuthorizationVisitor(ValidationContext context)
: base(context)
{
// optional: code to load the identity of the user here
}
protected override bool IsAuthenticated => false; // implement your logic here
protected override bool IsInRole(string role) => false; // implement your logic here
protected override ValueTask<AuthorizationResult> AuthorizeAsync(string policy)
=> new(AuthorizationResult.Failed()); // implement your logic here
}
public class MyAuthorizationRule : IValidationRule
{
// this is a singleton so there should be no user-specific code in the constructor
public virtual async ValueTask<INodeVisitor?> ValidateAsync(ValidationContext context)
{
var visitor = new MyAuthorizationVisitor(context);
// if the schema fails authentication, report the error and do not perform any additional authorization checks.
return await visitor.ValidateSchemaAsync(context) ? visitor : null;
}
}
builder.AddValidationRule<MyAuthorizationRule>(); |
Please note that if you add transport-level authentication requirements within the options of |
Thanks for your reply, I'll try it! |
Thank you for your reply, How to access http headers in Query or Mutation or Subscription method? and How to access http headers in MyAuthorizationRule? thanks. |
Inject IHttpContextAccessor into the constructor of MyAuthorizationRule |
Yes, public class MyAuthorizationRule : IValidationRule
} |
I’d probably just pass the relevant header(s) into the visitor, but there’s a few ways to implement it. Is it working? |
Yes, nject IHttpContextAccessor into the constructor of MyAuthorizationRule is good. |
Another option is to use the user context builder to initialize the UserContext based on the HttpContext. Then both the validation rule and individual methods have access to it. |
That's a good idea, how to do this: |
Thank for you. |
Thank you. I just wanted to comment that I had the same problem building an internal enterprise application. This particular piece of code solved my problem. |
@sungam3r Perhaps we should not check that |
I just ran into the same issue. Setting IsAuthenticated == true solved it, but finding the reason for this behaviour caused some headaches. |
Program:
Query:
MinimumAgeRequirement :
MinimumAgeHandler :
Error accessing "companyAll":
The text was updated successfully, but these errors were encountered: