Authentication
Authentication determines a user's identity. It is a prerequisite for authorization and also lets you access the authenticated user in your resolvers, for example to build a me field that returns the current user's profile.
Hot Chocolate integrates with the ASP.NET Core authentication system, so you can reuse existing authentication configuration and any supported authentication provider.
Learn more about authentication in ASP.NET Core
Setup
Setting up authentication follows the same pattern as any ASP.NET Core application. The example below uses JWT bearer tokens, but you can substitute any authentication scheme that ASP.NET Core supports.
1. Install the JWT Bearer Package
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearerHotChocolate.* packages need to have the same version.2. Register the Authentication Scheme
// Program.csvar 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. Use a proper key management solution for production.
3. Add Authentication Middleware
Register the authentication middleware in the request pipeline:
// Program.csapp.UseRouting();app.UseAuthentication();
app.UseEndpoints(endpoints =>{ endpoints.MapGraphQL();});
4. Install the Hot Chocolate Authorization Package
dotnet add package HotChocolate.AspNetCore.AuthorizationHotChocolate.* packages need to have the same version.5. Register Authorization on the Schema
// Program.csbuilder .AddGraphQL() .AddAuthorization() .AddQueryType<Query>();
Calling AddAuthorization() on the IRequestExecutorBuilder registers the @authorize directive and makes the authenticated user's identity available to resolvers. It does not lock out unauthenticated users. To restrict access, use authorization.
Accessing the ClaimsPrincipal
After authentication, the ClaimsPrincipal of the current user is available in your resolvers.
// Types/UserQueries.cs[QueryType]public static partial class UserQueries{ public static User? GetMe(ClaimsPrincipal claimsPrincipal, UserService users) { var userId = claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier);
if (userId is null) { return null; }
return users.GetById(userId); }}
Use ClaimsPrincipal to read claims such as the user ID, email, or roles:
var userId = claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier);var email = claimsPrincipal.FindFirstValue(ClaimTypes.Email);var isAdmin = claimsPrincipal.IsInRole("Administrator");
Modifying the ClaimsPrincipal
If you need to add claims or identities to the ClaimsPrincipal before it reaches your resolvers, register an IHttpRequestInterceptor:
// Interceptors/HttpRequestInterceptor.cspublic class HttpRequestInterceptor : DefaultHttpRequestInterceptor{ public override ValueTask OnCreateAsync( HttpContext context, IRequestExecutor requestExecutor, OperationRequestBuilder requestBuilder, CancellationToken cancellationToken) { var identity = new ClaimsIdentity(); identity.AddClaim(new Claim(ClaimTypes.Country, "us")); context.User.AddIdentity(identity);
return base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken); }}
// Program.csbuilder .AddGraphQL() .AddHttpRequestInterceptor<HttpRequestInterceptor>();
Next Steps
- Need to restrict access to fields? See Authorization.
- Need an overview of security options? See Security Overview.
- Need to customize request handling? See Interceptors.