danielwertheim

danielwertheim


notes from a passionate developer

Share


Sections


Tags


Disclaimer

This is a personal blog. The opinions expressed here represent my own and not those of my employer, nor current or previous. All content is published "as is", without warranty of any kind and I don't take any responsibility and can't be liable for any claims, damages or other liabilities that might be caused by the content.

GraphQL.NET and endpoint authorization in ASP.NET Core 3.1

Had my first experience with setting up a GraphQL API in ASP.NET Core 3.1 today using GraphQL-DotNet. Using their examples as inspiration to get started you'll find that there's nothing in the .NET Core sample regarding on how-to protect the endpoint that their middleware maps to. So in this post I'll show how you can leverage the ASP.NET Core Routing & Endpoints construct to require authorization against a middleware.

Following the linked examples above and reading documentation chances are big that you will end up with a Startup looking something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<PetsSchema>();

    services
        .AddGraphQL(opts =>
            opts.EnableMetrics = true)
        .AddErrorInfoProvider(opts =>
            opts.ExposeExceptionStackTrace = true)
        .AddSystemTextJson()
        .AddGraphTypes(typeof(PetsSchema));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();

    app.UseGraphQL<PetsSchema>();
}

Now, how would you, in an easy way, go ahead and ensure that the middleware being hooked in via app.UseGraphQL();requires authorization? Endpoints to the rescue. First lets create an extension point for hooking in the middleware:

using GraphQL.Server.Transports.AspNetCore;
using GraphQL.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;

namespace GqlLab.Api
{
    public static class GraphQlEndpointRouteBuilderExtensions
    {
        public static IEndpointConventionBuilder MapGraphQl<TSchema>(
            this IEndpointRouteBuilder endpoints, 
            string pattern = "/graphql") where TSchema : ISchema
        {
            var pipeline = endpoints
                .CreateApplicationBuilder()
                .UseMiddleware<GraphQLHttpMiddleware<TSchema>>(new PathString())
                .Build();
                
            return endpoints.Map(pattern, pipeline);
        }
    }
}

Now, lets hook it in:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGraphQl<PetsSchema>();
    });
}

You should now be able to run it as usual. At this point, the /graphql endpoint is still not secured. Lets fix that.

For the final step, lets require authorization. Please note! I'll not Configure Authentication properly. For that you can consult the official documentation etc.

public void ConfigureServices(IServiceCollection services)
{
    //TODO: Needs proper setup!
    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer();

    services.AddAuthorization();

    services.AddSingleton<PetsSchema>();

    services
        .AddGraphQL(opts =>
            opts.EnableMetrics = true)
        .AddErrorInfoProvider(opts =>
            opts.ExposeExceptionStackTrace = true)
        .AddSystemTextJson()
        .AddGraphTypes(typeof(PetsSchema));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints
            .MapGraphQl<PetsSchema>()
            .RequireAuthorization();
    });
}

That's it. No more "unsecured" /graphql endpoint. Remember, you still need to configure proper authentication etc. e.g. using JWT or Cookies.

Cheers,

//Daniel

View Comments