How to Protect GraphQL Queries with Authentication
To protect a query in
GraphQL, add authentication logic in the resolver by checking the user's identity from the request context. Use middleware or context setup to verify tokens or sessions before allowing query execution.Syntax
In GraphQL, authentication is usually done inside the resolver functions or middleware. The resolver receives a context object that contains user information after authentication. You check this user info before returning data.
context.user: holds authenticated user info.throw new Error(): stops query if user is not authenticated.
javascript
const resolvers = { Query: { protectedData: (parent, args, context) => { if (!context.user) { throw new Error('Not authenticated'); } return 'Secret data for ' + context.user.name; } } };
Example
This example shows a simple GraphQL server using express and express-graphql. It checks a fake token in headers and sets context.user. The protectedData query returns data only if authenticated.
javascript
const express = require('express'); const { graphqlHTTP } = require('express-graphql'); const { buildSchema } = require('graphql'); // Define schema const schema = buildSchema(` type Query { protectedData: String } `); // Root resolver const root = { protectedData: (parent, args, context) => { if (!context.user) { throw new Error('Not authenticated'); } return `Hello, ${context.user.name}. This is protected data.`; } }; const app = express(); // Middleware to simulate authentication app.use((req, res, next) => { const token = req.headers['authorization']; if (token === 'Bearer validtoken') { req.user = { name: 'Alice' }; } next(); }); app.use('/graphql', graphqlHTTP(req => ({ schema: schema, rootValue: root, context: { user: req.user }, graphiql: true }))); app.listen(4000, () => console.log('Server running on http://localhost:4000/graphql'));
Output
Query: { protectedData }
Response if authorized: { "data": { "protectedData": "Hello, Alice. This is protected data." } }
Response if unauthorized: { "errors": [{ "message": "Not authenticated" }] }
Common Pitfalls
- Not passing user info in
contextcauses authentication checks to fail. - Throwing errors without clear messages can confuse clients.
- Checking authentication only on the client side is insecure; always check on server.
- Forgetting to protect all sensitive queries or mutations leaves data exposed.
javascript
/* Wrong: No context user check */ const resolversWrong = { Query: { protectedData: () => { return 'Secret data'; // No authentication check } } }; /* Right: Check context.user */ const resolversRight = { Query: { protectedData: (parent, args, context) => { if (!context.user) { throw new Error('Not authenticated'); } return 'Secret data for ' + context.user.name; } } };
Quick Reference
- Use
contextto pass authenticated user info to resolvers. - Check
context.userin every protected resolver. - Throw errors to block unauthorized access.
- Use middleware to verify tokens before GraphQL execution.
- Protect both queries and mutations that expose sensitive data.
Key Takeaways
Always check user authentication inside GraphQL resolvers using the context object.
Use middleware to verify tokens and set user info before query execution.
Throw errors in resolvers to prevent unauthorized data access.
Never rely on client-side checks alone for security.
Protect all sensitive queries and mutations consistently.