How to Implement Role Based Access in GraphQL
To implement
role based access in GraphQL, define user roles and check these roles in your resolver functions or middleware using the context object. This allows you to restrict or allow access to specific queries or mutations based on the user's role.Syntax
Role based access in GraphQL typically involves checking the user's role inside resolver functions or middleware before returning data. The context object carries user info, including roles, for each request.
context.user.role: The user's role from authentication.resolver: Function that returns data, where role checks happen.throw new Error(): Used to deny access if role is insufficient.
javascript
const resolvers = { Query: { sensitiveData: (parent, args, context) => { if (context.user.role !== 'admin') { throw new Error('Access denied: Admins only'); } return 'Sensitive admin data'; } } };
Example
This example shows a simple GraphQL server where the sensitiveData query is accessible only to users with the admin role. The user's role is passed in the context during each request.
javascript
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type Query { sensitiveData: String } `; const resolvers = { Query: { sensitiveData: (parent, args, context) => { if (context.user.role !== 'admin') { throw new Error('Access denied: Admins only'); } return 'Sensitive admin data'; } } }; const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { // Simulate user extraction from request headers or token const user = { id: 1, role: req.headers.role || 'guest' }; return { user }; } }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
Output
Server ready at http://localhost:4000/
Common Pitfalls
Common mistakes when implementing role based access in GraphQL include:
- Not validating roles in every resolver that needs protection.
- Trusting client input for roles instead of verifying on the server.
- Not using the
contextproperly to pass authenticated user info. - Throwing generic errors that reveal sensitive info.
Always verify roles server-side and handle errors gracefully.
javascript
/* Wrong way: trusting client input directly */ const resolversWrong = { Query: { sensitiveData: (parent, args, context) => { if (args.role !== 'admin') { throw new Error('Access denied'); } return 'Sensitive data'; } } }; /* Right way: use context for verified user role */ const resolversRight = { Query: { sensitiveData: (parent, args, context) => { if (context.user.role !== 'admin') { throw new Error('Access denied'); } return 'Sensitive data'; } } };
Quick Reference
- Use
contextto pass authenticated user info including roles. - Check user roles inside resolvers or middleware before returning data.
- Throw errors to deny access when roles are insufficient.
- Never trust client input for roles; always verify on server.
Key Takeaways
Always pass authenticated user roles via the GraphQL context object.
Check user roles inside resolvers to control access to data.
Never trust client-provided role information; verify on the server.
Throw clear but secure errors when access is denied.
Protect every resolver that returns sensitive data with role checks.