SyntaxStudy
Sign Up
GraphQL JWT Authentication with Apollo Server
GraphQL Beginner 1 min read

JWT Authentication with Apollo Server

JWT (JSON Web Token) is the most common authentication mechanism for GraphQL APIs. The client obtains a token via a login mutation, then includes it in the Authorization header of every subsequent request. The Apollo Server context function runs before every operation and is the correct place to verify the token and attach the decoded user to context. The context function must never throw for unauthenticated requests—doing so would break public queries. Instead, set currentUser to null and let individual resolvers or graphql-shield rules enforce authentication where required.
Example
// npm install jsonwebtoken bcryptjs

import jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';

const JWT_SECRET = process.env.JWT_SECRET; // store in env, never hardcode

const typeDefs = `#graphql
  type AuthPayload {
    token: String!
    user: User!
  }
  type Mutation {
    login(email: String!, password: String!): AuthPayload!
    register(name: String!, email: String!, password: String!): AuthPayload!
  }
`;

const resolvers = {
  Mutation: {
    login: async (_, { email, password }, { db }) => {
      const user = await db.users.findByEmail(email);
      if (!user) throw new Error('Invalid credentials');
      const valid = await bcrypt.compare(password, user.passwordHash);
      if (!valid) throw new Error('Invalid credentials');
      const token = jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: '7d' });
      return { token, user };
    },
    register: async (_, { name, email, password }, { db }) => {
      const passwordHash = await bcrypt.hash(password, 12);
      const user = await db.users.create({ name, email, passwordHash });
      const token = jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: '7d' });
      return { token, user };
    },
  },
};

// Context function — runs for every request
async function context({ req }) {
  const authHeader = req.headers.authorization || '';
  const token = authHeader.startsWith('Bearer ') ? authHeader.slice(7) : null;
  let currentUser = null;
  if (token) {
    try {
      const { userId } = jwt.verify(token, JWT_SECRET);
      currentUser = await db.users.findById(userId);
    } catch { /* invalid/expired token */ }
  }
  return { currentUser, db };
}