Comments (10)
same here !
from authorization.
Can you post a list of the GraphQL-related nuget dependencies you are referencing?
from authorization.
from authorization.
Personally, I suggest removing the GraphQL.Server and GraphQL.Authorization packages and using GraphQL.AspNetCore3 instead, which is easy to use and has lots of documentation. We are in the process of replacing all the code in the GraphQL.Server.Transports.AspNetCore package with the code in the GraphQL.AspNetCore3 project, but it may be another month or more until that is complete. GraphQL.AspNetCore3 includes samples for configuration as ASP.Net Core middleware (the easiest way), or as a MVC controller action as it sounds like you have configured now.
You can also use the GraphQL.Server.Transports.AspNetCore and GraphQL.Server.Authorization.AspNetCore packages, but there are a number of authentication features not supported, which are supported in GraphQL.AspNetCore3.
As for your exact situation, can you provide a copy of your GraphQL controller and your DI configuration (as it relates to GraphQL services)? I am guessing that somehow the validation rule is not added to the execution options -- normally this happens automatically, but it can depend on your configuration.
from authorization.
My GraphQL Controller:
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Execution;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using rcRegman_CoCreation.Models;
namespace rcRegman_CoCreation.Controllers
{
[ApiController]
public class GraphQLController : Controller
{
private readonly IDocumentExecuter _executer;
private readonly ISchema _schema;
private static readonly GraphQLSerializer _serializer = new();
public GraphQLController(ISchema schema, IDocumentExecuter executer)
{
_schema = schema;
_executer = executer;
}
[Route("graphql")]
[HttpPost]
public async Task<cke:object> Post([FromBody] object query)
{
GraphqlErrors.Errors.Clear();
var rawJson = query.ToString();
var _query = JsonConvert.DeserializeObject<GraphQLQueryDTO>(rawJson);
var result = await _executer.ExecuteAsync(_ =>
{
_.Schema = _schema;
_.Query = _query.Query;
_.Variables = _serializer.Deserialize<Inputs>(rawJson);
_.UserContext = new GraphQlUserContextDictionary(User);
});
if (result.Errors?.Count > 0)
{
for (var i = 0; i < result.Errors.Count; i++) GraphqlErrors.Errors.Add(result.Errors[i].Message);
return BadRequest(GraphqlErrors.Errors);
}
var returnObject = new ExecutionResult();
returnObject.Data =((ExecutionNode)result.Data).ToValue();
return Ok(returnObject);
}
}
}
Statup.cs
public void ConfigureServices(IServiceCollection services)
{
....
services.AddSingleton<IServiceProvider>(_ => new FuncServiceProvider(_.GetRequiredService));
// GraphQL Schema
services.AddSingleton<CompositeQuery>();
services.AddSingleton<CompositeMutation>();
// GraphQL Query DI
services.AddSingleton<IGraphQueryMarker, CommentQuery>();
....
}
CompositeQuery:
using System.Collections.Generic;
using GraphQL.Types;
using rcRegman_CoCreation.GraphQL.Marker;
namespace rcRegman_CoCreation.GraphQL.Query
{
public class CompositeQuery : ObjectGraphType
{
public CompositeQuery(IEnumerable<IGraphQueryMarker> graphQueryMarkers)
{
Name = "CompositeQuery";
foreach (var marker in graphQueryMarkers)
{
var m = marker as ObjectGraphType<object>;
foreach (var f in m.Fields) AddField(f);
}
}
}
}
public interface IGraphQueryMarker
{
}
and CompositeMutation:
using System.Collections.Generic;
using GraphQL.Types;
using rcRegman_CoCreation.GraphQL.Marker;
namespace rcRegman_CoCreation.GraphQL.Mutation
{
public class CompositeMutation : ObjectGraphType
{
public CompositeMutation(IEnumerable<IGraphMutationMarker> graphMutationMarkers)
{
Name = "CompositeMutation";
foreach (var marker in graphMutationMarkers)
{
var m = marker as ObjectGraphType;
foreach (var f in m.Fields) AddField(f);
}
}
}
}
I have also tried changing to the GraphQL.AspNetCore3 package and follow the documentation there. The authorization for all requests works. However I need to protect individual fields and when trying to configure it in startup like:
services.AddGraphQL(b => b
.AddSystemTextJson()
.AddAuthorization()
);
I'm getting the following error:
System.ArgumentNullException: Value cannot be null. (Parameter 'provider')
at GraphQL.Utilities.ServiceProviderExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) in /_/src/GraphQL/Utilities/ServiceProviderExtensions.cs:line 22
at GraphQL.Utilities.ServiceProviderExtensions.GetRequiredService[T](IServiceProvider provider) in /_/src/GraphQL/Utilities/ServiceProviderExtensions.cs:line 11
at GraphQL.GraphQLBuilderExtensions.<>c__DisplayClass64_0`1.<AddValidationRule>b__0(ExecutionOptions options) in /_/src/GraphQL/GraphQLBuilderExtensions.cs:line 968
at GraphQL.DI.ConfigureExecutionOptions.<>c__DisplayClass2_0.<.ctor>b__0(ExecutionOptions opt) in /_/src/GraphQL/DI/IConfigureExecutionOptions.cs:line 29
at GraphQL.DI.ConfigureExecutionOptions.ConfigureAsync(ExecutionOptions executionOptions) in /_/src/GraphQL/DI/IConfigureExecutionOptions.cs:line 34
at GraphQL.DI.ConfigureExecutionOptionsMapper.<>c__DisplayClass1_0.<<-ctor>b__0>d.MoveNext() in /_/src/GraphQL/DI/IConfigureExecutionOptions.cs:line 55
Maybe this is related to the issue I'm experiencing?
from authorization.
Well the last issue is easy. Set the RequestServices property to the service provider when calling the document executer.
From memory: (I’ll double check in a bit)
_.RequestServices = HttpContext.RequestServices;
from authorization.
You're also missing the cancellation token and the operation name, and variables are deserializing the entire json string rather than just the variables property, and the extensions property is also missing.
var result = await _executer.ExecuteAsync(_ =>
{
_.Schema = _schema;
_.Query = _query.Query;
_.OperationName = _query.OperationName;
_.Variables = _serializer.ReadNode<Inputs>(_query.Variables); // assuming that Variables is of type JsonElement
_.Extensions = _serializer.ReadNode<Inputs>(_query.Extensions); // assuming that Extensions is of type JsonElement
_.UserContext = new GraphQlUserContextDictionary(User);
_.RequestServices = HttpContext.RequestServices;
_.RequestAborted = HttpContext.RequestAborted;
});
There's another issue with my sample above, however: you're using Newtonsoft.Json to deserialize rawJson
but called AddSystemTextJson
to use the System.Text.Json GraphQL deserializer. As such, Variables
and Extensions
should be a JObject
, and in order to read them via ReadNode
you need to use AddNewtonsoftJson
. Or, use System.Text.Json to deserialize the rawJson
.
I would strongly suggest reviewing the controller sample for GraphQL.AspNetCore3
:
I also noticed that you registered IServiceProvider
. Typically this is provided by your DI implementation and does not need to be registered. If it does need to be registered, it is very important that this is a scoped service, not a singleton. And finally, it's pointing to GetRequiredService
instead of GetService
, which is incorrect behavior for an IServiceProvider
implementation as it will throw an exception if a service is not registered. GraphQL relies on the correct implementation of IServiceProvider
.
// remove this line !!!!!
services.AddSingleton<IServiceProvider>(_ => new FuncServiceProvider(_.GetRequiredService));
from authorization.
I updated the controller sample to demonstrate WebSocket support as well, although at that point you might as well use the middleware, which is much simpler to use. Just call app.UseGraphQL("/graphql");
in your startup and you can remove the controller entirely. You'd also probably need to set up the user context builder when you configure GraphQL:
.AddUserContextBuilder(context => new GraphQlUserContextDictionary(context.User));
from authorization.
That did solve the problem. The authorization now works like a charm.
Big thanks to you for your help!
from authorization.
@fl99kl Long story short - add IProvideClaimsPrincipal
to your GraphQlUserContextDictionary
:
public class GraphQlUserContextDictionary : Dictionary<string, object>, IProvideClaimsPrincipal
{
public ClaimsPrincipal User { get; set; }
public GraphQlUserContextDictionary(ClaimsPrincipal User)
{
this.User = User;
}
}
from authorization.
Related Issues (20)
- Checking for a valid JWT and integrating with a Refresh-Token-Workflow HOT 10
- UNAUTHENTICATED error code HOT 3
- In AuthorizationValidationRule.cs the method CheckAuth is called multiple times. Why? HOT 4
- ETA for v4? HOT 18
- IAuthorizationRequirement is not sent the same variable names as those in IResolveField context HOT 2
- ClaimsPrincipal not retrived trying to use AuthorizeWith in GraphQL queries HOT 6
- Any example for schema first auth example? HOT 2
- How to get a status code 401 when not authorized HOT 6
- Move GraphQLAuthExtensions from Harness into new package HOT 6
- Add docs about IAuthorizationSkipCondition and DI
- Method 'ValidateAsync' in type 'GraphQL.Authorization.AuthorizationValidationRule' from assembly 'GraphQL.Authorization, Version=4.0.0.0 HOT 7
- GraphQL .net authorization with JWT token HOT 7
- AddGraphQLAuth no longer works after switching to Middleware HOT 1
- Return 401 and 403 status code HOT 5
- Is this library still relevant with GraphQL 7+ HOT 22
- How to read graphql query from authorization requirement ?
- Compatibility with GraphQL .NET 8.x HOT 1
- question - Authorize only without policy HOT 3
- How to login user and return token and id ? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from authorization.