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