server: Duende Identity Server 4 / GraphQl Authorize - Always error 403

Hi,

somehow i’m not able to get authentication working properly - I’m using DuendeIdentityServer4 with JWT Tokens (this is working proper with SignalR and Rest APIs). Now I tried to include GraphQL to that process as well, but I don’t achieve any success there.

All queries (with valid JWT Tokens) returning 401/403 with those logs:

[2023-07-04T11:21:08.209] [INFO] [Microsoft.AspNetCore.Hosting.Diagnostics] [] [] [Request starting HTTP/1.1 POST http://localhost:5000/graphql application/json 615  ] [0] [Protocol=HTTP/1.1, Method=POST, ContentType=application/json, ContentLength=615, Scheme=http, Host=localhost:5000, Path=/graphql, EventId=1]
[2023-07-04T11:21:08.223] [DEBUG] [Microsoft.AspNetCore.Cors.Infrastructure.CorsService] [] [] [The request has an origin header: 'http://localhost:5000'.  ] [0] [origin=http://localhost:5000, EventId=2, EventName=RequestHasOriginHeader]
[2023-07-04T11:21:08.242] [INFO] [Microsoft.AspNetCore.Cors.Infrastructure.CorsService] [] [] [CORS policy execution successful.  ] [0] [EventId=4, EventName=PolicySuccess]
[2023-07-04T11:21:08.253] [DEBUG] [Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware] [] [] [POST requests are not supported  ] [0] [Method=POST, EventId=1, EventName=MethodNotSupported]
[2023-07-04T11:21:08.272] [INFO] [Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware] [] [] [No CORS policy found for the specified request.  ] [0] [EventId=10, EventName=NoCorsPolicyFound]
[2023-07-04T11:21:08.282] [DEBUG] [Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler] [] [] [AuthenticationScheme: idsrv was successfully authenticated.  ] [0] [AuthenticationScheme=idsrv, EventId=8, EventName=AuthenticationSchemeAuthenticated]
[2023-07-04T11:21:08.282] [DEBUG] [Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler] [stefan.koenig] [] [AuthenticationScheme: idsrv was successfully authenticated.  ] [0] [AuthenticationScheme=idsrv, EventId=8, EventName=AuthenticationSchemeAuthenticated]
[2023-07-04T11:21:08.282] [DEBUG] [Microsoft.AspNetCore.Routing.Matching.DfaMatcher] [stefan.koenig] [] [No candidates found for the request path '/graphql'  ] [0] [Path=/graphql, EventId=1000, EventName=CandidatesNotFound]
[2023-07-04T11:21:08.297] [DEBUG] [Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware] [stefan.koenig] [] [Request did not match any endpoints  ] [0] [EventId=2, EventName=MatchFailure]
[2023-07-04T11:21:08.297] [DEBUG] [Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler] [stefan.koenig] [] [AuthenticationScheme: idsrv was successfully authenticated.  ] [0] [AuthenticationScheme=idsrv, EventId=8, EventName=AuthenticationSchemeAuthenticated]
[2023-07-04T11:21:08.297] [DEBUG] [Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware] [stefan.koenig] [] [POST requests are not supported  ] [0] [Method=POST, EventId=1, EventName=MethodNotSupported]
[2023-07-04T11:21:08.317] [DEBUG] [Microsoft.AspNetCore.ResponseCompression.ResponseCompressionProvider] [stefan.koenig] [] [The response will be compressed with 'br'.  ] [0] [provider=br, EventId=8, EventName=CompressWith]
[2023-07-04T11:21:08.332] [DEBUG] [Microsoft.AspNetCore.Server.Kestrel.Connections] [stefan.koenig] [] [Connection id "0HMRSDPUR99KJ" completed keep alive response.  ] [0] [ConnectionId=0HMRSDPUR99KJ, EventId=9, EventName=ConnectionKeepAlive]
[2023-07-04T11:21:08.332] [INFO] [Microsoft.AspNetCore.Hosting.Diagnostics] [stefan.koenig] [] [Request finished HTTP/1.1 POST http://localhost:5000/graphql application/json 615 - 403 - application/json;+charset=utf-8 115.5603ms  ] [0] [ElapsedMilliseconds=115.5603, StatusCode=403, ContentType=application/json; charset=utf-8, Protocol=HTTP/1.1, Method=POST, Scheme=http, Host=localhost:5000, Path=/graphql, EventId=2]
[2023-07-04T11:21:08.332] [DEBUG] [Microsoft.AspNetCore.Server.Kestrel] [] [] [Connection id "0HMRSDPUR99KJ", Request id "0HMRSDPUR99KJ:00000001": started reading request body.  ] [0] [ConnectionId=0HMRSDPUR99KJ, TraceIdentifier=0HMRSDPUR99KJ:00000001, EventId=25, EventName=RequestBodyStart]
[2023-07-04T11:21:08.332] [DEBUG] [Microsoft.AspNetCore.Server.Kestrel] [] [] [Connection id "0HMRSDPUR99KJ", Request id "0HMRSDPUR99KJ:00000001": done reading request body.  ] [0] [ConnectionId=0HMRSDPUR99KJ, TraceIdentifier=0HMRSDPUR99KJ:00000001, EventId=26, EventName=RequestBodyDone]

I did it like that:

Startup.cs

  services.AddGraphQL(builder => builder
         .AddUserContextBuilder(httpContext => new UserContext(httpContext.User))
         .AddAuthorizationRule()
         .AddSchema<MySchema>()
         .ConfigureExecutionOptions(options =>
         {
             options.EnableMetrics = Environment.IsDevelopment();
             options.UnhandledExceptionDelegate = ctx =>
             {
                 logger.Error($"Uncaught GraphQl Exception -> {ctx.ErrorMessage}", ctx.Exception);
                 return Task.CompletedTask;
             };
         })
         .AddNewtonsoftJson() // For everything else
         .AddErrorInfoProvider(opt => opt.ExposeExceptionDetails = true)
     );
        app.UseGraphQL("/graphql", config =>
        {
            config.AuthorizedRoles.Add("role.manager.access");
            config.AuthorizationRequired = true;
        });
        app.UseGraphQLAltair();
        app.UseGraphQLPlayground();

My Root Query is annotated with

[Authorize(Policy = "user.api..manager")]

Do you have any idea what I’m doing wrong?

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

Works for my server. Look for an updated version of GraphQL.NET Server 7 shortly with the new property. It seems that my old notes shown here were actually mostly correct, but it didn’t follow through setting the context.User property to the result.

//-- and you'd think this would work: --
//var auth = context.RequestServices.GetRequiredService<IAuthenticationService>();
//await auth.AuthenticateAsync(context, JwtBearerDefaults.AuthenticationScheme);

See the PR for the proposed implementation. My server code now looks like this, which is a substantial improvement:

                endpoints.MapGraphQL(
                    "/graphql",
                    opts => {
                        opts.HandleGet = false;
                        // GraphQL requests will ignore cookie authentication and use JWT authentication only
                        opts.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
                        opts.AuthorizationRequired = true;
                        opts.AuthorizedRoles.Add("myRole");
                    })
                    .RequireCors("GraphQL");