What is JWT Verification in GraphQL in Simple Terms?
JWT (JSON Web Token) is a secure token used to identify users.
After login:
- Server generates a token
- Client sends token with every request
- Server verifies token before executing resolver
Example token format:
xxxxx.yyyyy.zzzzzCode language: CSS (css)Why JWT After Merging Resolvers?
This guide is a continuation of our previous post on building scalable resolvers:
“How to Merge Multiple Resolvers in GraphQL”
In the previous blog, you learned how to organize and merge resolvers efficiently. But here’s the real question:
👉 What if anyone can access those resolvers?
Without authentication:
- Anyone can query sensitive data
- APIs become vulnerable
- No control over user access
So now, we secure our resolvers using JWT verification.
How JWT Fits into GraphQL Flow
Now connect this with your resolver architecture:
Step-by-step flow:
Now your full flow looks like this:
- Login → Generate JWT
- Client stores token
- Client sends token in header
- Context verifies token
- Resolver checks
context.user
Once your GraphQL API structure is ready, the next critical step is securing those resolvers. That’s where JWT (JSON Web Token) verification comes into play.
Add JWT Verification to Your Existing GraphQL Setup
You already have merged resolvers. Now we enhance them.
Step 1: Install JWT Package
npm install jsonwebtokenStep 2: Generate JWT on Login
You need a login mutation in your GraphQL API. In VS code inside src folder make Login resolvers. Inside this folder make to file 1-resolvers and schema.graphql and copy and paste the below code.
Login Resolver
import jwt from 'jsonwebtoken';
const SECRET_KEY = process.env.JWT_SECRET;
const resolvers = {
Mutation: {
login: async (_, { email, password }) => {
// 1. Validate user (DB check)
const user = await findUserByEmail(email);
if (!user || user.password !== password) {
throw new Error('Invalid credentials');
}
// 2. Generate JWT
const token = jwt.sign(
{ id: user.id, email: user.email, role: user.role },
SECRET_KEY,
{ expiresIn: '1h' }
);
// 3. Send token to client
return {
token,
user,
};
},
},
};Code language: JavaScript (javascript)Basic Login Schema
type User {
id: ID!
email: String!
role: String
}
type AuthPayload {
token: String!
user: User!
}
type Mutation {
login(email: String!, password: String!): AuthPayload!
}Code language: JavaScript (javascript)Step 3: Create JWT Verification Utility
import jwt from 'jsonwebtoken';
const SECRET_KEY = process.env.JWT_SECRET;
export const verifyToken = (token) => {
try {
return jwt.verify(token, SECRET_KEY);
} catch (error) {
return null;
}
};Code language: JavaScript (javascript)Step 4: Inject User into GraphQL Context
This is the most important step.
import { verifyToken } from './utils/jwt';
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const authHeader = req.headers.authorization || '';
const token = authHeader.replace('Bearer ', '');
const user = verifyToken(token);
return { user };
},
});Code language: JavaScript (javascript)👉 Now every resolver has access to context.user
Securing Your Existing Resolvers
In your previous blog, your message resolvers is like this:
const resolvers = {
Query: {
appMessage() {
return "This response is coming from the message module.";
},
},
};
export default resolvers;Code language: JavaScript (javascript)Now update it with JWT protection:
const resolvers = {
Query: {
appMessage(_,_,context) {
if (!context.user) {
throw new Error('Unauthorized');
}
return "This response is coming from the message module.";
},
},
};
export default resolvers;Code language: JavaScript (javascript)Update Package.json file also
{
"name": "jwt_varification",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@apollo/server": "^5.5.0",
"@apollo/subgraph": "^2.14.0",
"@as-integrations/express5": "^1.1.2",
"cors": "^2.8.6",
"express": "^5.2.1",
"graphql": "^16.13.2",
"graphql-tag": "^2.12.6",
"jsonwebtoken": "^9.0.3"
}
}
Code language: JSON / JSON with Comments (json)Final Index.js code
import express from "express";
import cors from "cors";
import gql from "graphql-tag";
import { ApolloServer } from "@apollo/server";
import { buildSubgraphSchema } from "@apollo/subgraph";
import { expressMiddleware } from "@as-integrations/express5";
import recordResolvers from "./records/resolvers.js";
import messageResolvers from "./message/resolvers.js";
import loginResolvers from "./Login/resolvers.js";
import { verifyToken } from "./util/verifyToken.js";
import { readFileSync } from "fs";
import { createServer } from "http";
const PORT = 5000;
const app = express();
const httpServer = createServer(app);
const typeDefs = gql(`
${readFileSync("./src/records/schema.graphql")}
${readFileSync("./src/message/schema.graphql")}
${readFileSync("./src/Login/schema.graphql")}
`);
const resolvers = {
Query: {
...recordResolvers.Query,
...messageResolvers.Query,
},
Mutation: {
...loginResolvers.Mutation,
},
};
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers }),
});
const context = async ({ req }) => {
const authHeader = req.headers.authorization || "";
const token = authHeader.replace("Bearer ", "");
const user = verifyToken(token);
return { user };
};
await server.start();
app.use(
"/graphql",
cors(),
express.json(),
expressMiddleware(server, { context })
);
httpServer.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/graphql`);
});
httpServer.on("error", (error) => {
console.error("Failed to start server:", error);
});
Code language: JavaScript (javascript)Folder structure

Common Mistakes Developers Make
Avoid these issues:
- ❌ Not checking token in every resolver
- ❌ Trusting token without verification
- ❌ No token expiration
- ❌ Storing JWT in localStorage (security risk)
Step 5: How Client Sends JWT
After login, the client must include the token in every request.
Method 1: Using Authorization Header
Authorization: Bearer <your_token>Code language: HTML, XML (xml)Example (Frontend using Fetch)
fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
query: `Query {
appMessage
}`,
}),
});Code language: JavaScript (javascript)Step 6: How to Test JWT in GraphQL
You can test this easily using tools like:
- Postman
- GraphQL Playground
🔹 Test Flow in Postman
- Call login mutation
{
"query": "mutation { login(email: \"test@mail.com\", password: \"1234\") { token } }"
}Code language: JSON / JSON with Comments (json)- Copy the token from response
- Call protected query with header:
Authorization: Bearer <token>Code language: HTML, XML (xml)🔹 Test Flow in GraphQL Playground
get JWT token

use it in message resolver

{
"Authorization": "Bearer your_token_here"
}Code language: JSON / JSON with Comments (json)Then run:
query {
getUserProfile {
id
email
}
}Conclusion
In the previous blog, you structured your GraphQL resolvers.
In this guide, you secured them using JWT.
👉 Together, these two steps create:
- Scalable APIs
- Secure data access
- Production-ready GraphQL systems