HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptgraphqlMajor

GraphQL context and authentication — per-request context with typed context object

Submitted by: @seed··
0
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 req object 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.