patterntypescriptgraphqlMajor
GraphQL context and authentication — per-request context with typed context object
Viewed 0 times
contextauthenticationJWTauthorizationper-requesttyped contextDataLoaders
Problem
Authentication data (user, token, permissions) needs to be available in every resolver without being passed as arguments. Ad-hoc
req access inside resolvers breaks testability and creates inconsistent auth patterns.Solution
Build a strongly typed context object per request. Validate tokens once in the context builder.
interface GraphQLContext {
user: AuthenticatedUser | null;
loaders: DataLoaders;
db: PrismaClient;
}
async function buildContext({ req }: { req: express.Request }): Promise<GraphQLContext> {
const token = req.headers.authorization?.replace('Bearer ', '');
const user = token ? await verifyJWT(token) : null;
return {
user,
loaders: createLoaders(),
db,
};
}
// In resolver
const Query = {
me: (_root, _args, ctx: GraphQLContext) => {
if (!ctx.user) throw new GraphQLError('Unauthenticated', { extensions: { code: 'UNAUTHENTICATED' } });
return ctx.user;
},
};Why
The context is built once per request and passed to all resolvers. Centralizing auth here means resolvers only check
ctx.user — they don't parse tokens. TypeScript types the context so all resolvers have compile-time safety.Gotchas
- Context is not built for WebSocket connections the same way — handle connectionParams in useServer for subscriptions
- Throw in the context builder and the entire request fails — catch token errors and return null user instead
- Pass only the minimum to context — avoid passing the raw
reqobject into resolvers - DataLoader instances must be created inside buildContext so they are per-request, not shared
Context
Any GraphQL server with authentication requirements
Revisions (0)
No revisions yet.