Why does GraphQL .Net HttpConext not have the correct user session?

1.1k views Asked by At

I am using GraphQL .net to respond to graphql queries on the backend of an Asp.net Core website. All the cookies seem to be passed with the requests but for some reason my graphql.net requests do not have the proper user session set on the HttpContext. The ClaimPrincipal is mostly empty via graphql.net while my Asp.net Core WebApi/Mvc style endpoints have the correct principal with user id even though both GraphQl.Net requests and non-graphql.net requests are happening at the same time.

I checked the payload and all the same cookies are passed in both requests. So it makes me wonder why are my regular WebApi endpoints able to (auto-magically) get the claims principal and why can't the graph.net endpoints do the same. As far as I know from previous usages of GraphQl.net I wasn't aware that any special session code had to be added (other than passing the user from the HttpContext to graphQL.net). I've been reading through GraphQL.Net and Asp.net core source code and docs, but so far I haven't found any obvious offenses or leads.

What might cause some issue like this? what are some common causes? Should I just try to figure out how to manually read in the cookie to Asp.net core and pull the principal?

Perhaps I'm missing a special header value? I don't think the headers are weird but I haven't done a side by side comparison between the headers in graphql.net and asp.net core requests.

In this snippet is where I first detect a problem. If I put a breakpoint here then the claimsprinical isn't correctly set for the current user session. And also later when I access the HttpContext the user session is not correct for graphql.net requests.

public static GraphQLUserContext InitializeFromContext(HttpContext httpContext)
{
       return new GraphQLUserContext
       {
            User = httpContext.User,
       };
}

Here's part of the Graphql.net configuration:

services.AddGraphQL((options, provider) =>
                {
                    options.EnableMetrics = _env.IsDevelopment();
                    var logger = provider.GetRequiredService<ILogger<WebDependencyInjectionConfig>>();
                    options.UnhandledExceptionDelegate = ctx => logger.LogError("{Error} occurred", ctx.OriginalException.Message);
                })
                .AddErrorInfoProvider(opt =>
                {
                    opt.ExposeExceptionStackTrace = _env.IsDevelopment();
                    opt.ExposeCodes = _env.IsDevelopment();
                    opt.ExposeCode = _env.IsDevelopment();
                    opt.ExposeData = _env.IsDevelopment();
                    opt.ExposeExtensions = _env.IsDevelopment();
                })
                .AddSystemTextJson()

                .AddUserContextBuilder(GraphQLUserContext.InitializeFromContext)
                .AddGraphTypes(typeof(PrimarySchema), ServiceLifetime.Scoped);

I'll gladly provide any requested configuration if anyone wants it, but there is a lot of possible code it touches. Thanks!

1

There are 1 answers

1
Joe McBride On BEST ANSWER

What does your Configure method look like? Is your app.UseAuthentication() before your GraphQL middleware configuration?

public void Configure(IApplicationBuilder app)
{
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseGraphQL<MySchema>();
}

https://github.com/dotnet/aspnetcore/blob/790c4dc2cf59e16e6144f7790328d563ca310533/src/Security/samples/Cookies/Startup.cs#L45-L66