website/src/docs/hotchocolate/v12/security/authentication.md
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
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.
Microsoft.AspNetCore.Authentication.JwtBearer packagepublic class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var signingKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("MySuperSecretKey"));
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidIssuer = "https://auth.chillicream.com",
ValidAudience = "https://graphql.chillicream.com",
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey
};
});
}
}
Warning: This is an example configuration that's not intended for use in a real world application.
UseAuthenticationpublic class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
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.
HotChocolate.AspNetCore.Authorization packageAddAuthorization() on the IRequestExecutorBuilderservices
.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
The ClaimsPrincipal of an authenticated user can be accessed in our resolvers like the following.
<ExampleTabs> <Implementation>public class Query
{
public User GetMe(ClaimsPrincipal claimsPrincipal)
{
// Omitted code for brevity
}
}
public class QueryType : ObjectType
{
protected override void Configure(IObjectTypeDescriptor descriptor)
{
descriptor
.Field("me")
.Resolve(context =>
{
var claimsPrincipal = context.GetUser();
// Omitted code for brevity
});
}
}
services
.AddGraphQLServer()
.AddDocumentFromString(@"
type Query {
me: User
}
")
.AddResolver("Query", "me", (context) =>
{
var claimsPrincipal = context.GetUser();
// Omitted code for brevity
})
With the authenticated user's ClaimsPrincipal, we can now access their claims.
var userId = claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier);