Back to results for “Passport)”
Node.js › GraphQL

How would you implement authentication and authorization in a GraphQL API in Node.js, given there's typically only a single HTTP endpoint?

Advanced

Answer

Authentication is typically handled the same way as a REST API -- verifying a JWT or session from the request headers before the GraphQL execution begins, attaching the resulting user object to a shared 'context' object that Apollo Server passes to every resolver -- authorization then happens inside individual resolvers (or via a dedicated directive like @auth applied directly in the schema), checking the authenticated user from context against the specific field or operation being accessed, since GraphQL's single endpoint means you can't rely on route-level middleware the way a REST API might for path-specific authorization.
const server = new ApolloServer({
  typeDefs, resolvers,
  context: async ({ req }) => {
    const user = await verifyToken(req.headers.authorization);
    return { user };
  },
});

const resolvers = {
  Mutation: {
    deletePost: (_, { id }, context) => {
      if (!context.user || context.user.role !== 'admin') throw new GraphQLError('Forbidden');
      return db.posts.delete(id);
    },
  },
};
Real-world example A GraphQL API authenticates every incoming request once at the context-creation step, then checks the resulting context.user's role inside each sensitive resolver (like deletePost) individually, since GraphQL's single-endpoint design means authorization can't be scoped by URL path the way it commonly is in a REST API.

Common follow-ups: How would you implement a reusable authorization check that applies consistently across many resolvers without duplicating the check logic everywhere?;What's the tradeoff of field-level authorization (checking inside individual resolvers) versus a schema-level directive-based approach?