Authentication allows us to determine a user's identity. This is of course a prerequisite for authorization, but it also allows us to access the authenticated user in our resolvers. This is useful, if we for example want to build a me
field that fetches details about the authenticated user.
Hot Chocolate fully embraces the authentication capabilities of ASP.NET Core, making it easy to reuse existing authentication configuration and integrating a variety of authentication providers.
Learn more about authentication in ASP.NET Core
Setup
Setting up authentication is largely the same as in any other ASP.NET Core application.
In the following example we are using JWTs, but we could use any other authentication scheme supported by ASP.NET Core.
- Install the
Microsoft.AspNetCore.Authentication.JwtBearer
package
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
- Register the JWT authentication scheme
var signingKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes("MySuperSecretKey"));
builder.Services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = "https://auth.chillicream.com", ValidAudience = "https://graphql.chillicream.com", ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey }; });
This is an example configuration that's not intended for use in a real world application.
- Register the ASP.NET Core authentication middleware with the request pipeline by calling
UseAuthentication
app.UseRouting();
app.UseAuthentication();
app.UseEndpoints(endpoints =>{ endpoints.MapGraphQL();});
The above takes care of parsing and validating an incoming HTTP request.
In order to make the authentication result available to our resolvers, we need to complete some additional, Hot Chocolate specific steps.
- Install the
HotChocolate.AspNetCore.Authorization
package
dotnet add package HotChocolate.AspNetCore.Authorization
HotChocolate.*
packages need to have the same version.- Call
AddAuthorization()
on theIRequestExecutorBuilder
builder.Services .AddGraphQLServer() .AddAuthorization() .AddQueryType<Query>();
All of this does not yet lock out unauthenticated users. It only exposes the identity of the authenticated user to our application through a ClaimsPrincipal
. If we want to prevent certain users from querying our graph, we need to utilize authorization.
Learn more about authorization
Accessing the ClaimsPrincipal
The ClaimsPrincipal of an authenticated user can be accessed in our resolvers like the following.
public class Query{ public User GetMe(ClaimsPrincipal claimsPrincipal) { // Omitted code for brevity }}
With the authenticated user's ClaimsPrincipal
, we can now access their claims.
var userId = claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier);