Authentication Through GraphQL Context
A common GraphQL architecture authenticates the request before resolvers execute and places the authenticated identity into the GraphQL context.
Conceptually:
const context = async ({ req }) => {
const token = extractToken(req);
const user = await verifyToken(token);
return {
user,
requestId: req.headers["x-request-id"]
};
};
A resolver can then access the identity:
const resolvers = {
Query: {
me: (_, __, context) => {
if (!context.user) {
throw new Error("Authentication required");
}
return context.user;
}
}
};
The exact token verification mechanism depends on the application. It could involve a signed JWT, an opaque session token, a gateway, or another identity provider.
The important architectural principle is that authentication should happen consistently rather than requiring every resolver to independently parse and verify credentials.
A context object can also expose an authorization service:
return {
user,
authorizationService,
userService,
requestId
};
This keeps resolver code focused on API coordination rather than authentication implementation details.
const createContext = async ({ req }) => {
const token = extractBearerToken(req);
const user = token ? await verifyAccessToken(token) : null;
return {
user,
requestId: req.headers["x-request-id"] ?? crypto.randomUUID()
};
};
const resolvers = {
Query: {
me: (_, __, context) => {
if (!context.user) {
throw new Error("Authentication required");
}
return context.user;
}
}
};- Authenticate requests before resolver execution where practical.
- Expose authenticated identity through request-scoped context.
- Avoid duplicating token parsing across resolvers.
- Context can expose request-specific security and application services.
Why is request context commonly used to expose the authenticated user?