Prompt
How do I secure GraphQL APIs?
Latest observation
Securing GraphQL APIs is mostly about controlling who can do what, how expensive queries can get, and what data can be exposed. GraphQL gives clients a lot of flexibility, so the main risk is letting that flexibility become an attack surface.
Core practices
1. Authenticate every request
Use standard auth mechanisms:
- OAuth2 / OIDC
- JWTs
- Session cookies for browser apps
Make sure the API can reliably identify the caller before resolving any sensitive data.
2. Authorize at the field/object level
GraphQL often exposes many fields through one endpoint, so coarse endpoint-based auth is not enough.
Best practice:
- Check permissions in resolvers
- Enforce authorization per object, field, or action
- Don’t rely only on the client hiding fields
Example:
- A user may read their own
email - Only admins may read
salary - Only owners may update their own records
3. Disable introspection in production only if appropriate
Introspection is useful for development, tooling, and debugging, but it can also help attackers map your schema.
Options:
- Keep introspection enabled for authenticated/internal users
- Restrict it in public environments
- Don’t assume disabling introspection is sufficient security
4. Limit query complexity
Attackers can craft queries that are expensive even if they are valid.
Use:
- Depth limits
- Complexity / cost analysis
- Field-specific weighting
- Pagination requirements
Examples of costly patterns:
- Very deep nested queries
- Large fan-out relations
- Repeated aliases
- Fragment recursion-like patterns
5. Rate limit and throttle
Apply rate limits based on:
- IP
- user
- token/client
- query cost
GraphQL requests are not all equal, so cost-based rate limiting is better than raw request counts.
6. Prevent abusive batching and aliasing
GraphQL lets clients ask for many similar operations in one request.
Protect against:
- Multiple expensive aliases
- Excessive batching
- Large numbers of resolver calls in one query
7. Validate and sanitize inputs
Treat all GraphQL arguments as untrusted:
- Validate types and lengths
- Enforce enums and allowed values
- Use allowlists for sort/filter fields
- Avoid passing user input directly into SQL, shell commands, or NoSQL queries
8. Avoid overexposing your schema
A GraphQL schema can become a data dictionary for attackers.
Reduce exposure by:
- Only modeling necessary types/fields
- Marking deprecated fields and removing them eventually
- Not exposing internal-only fields
- Using separate schemas or views for public vs internal APIs
9. Use DataLoader or equivalent to prevent N+1 abuse
This is partly performance, partly security. Without batching/caching, attackers can trigger many backend calls with one request.
10. Protect against CSRF if using cookies
If your GraphQL API uses browser cookies for auth:
- Use CSRF tokens
- Set
SameSitecookies appropriately - Validate
Origin/Refererfor state-changing operations
11. Restrict file uploads and subscriptions
If supported:
- Validate file types, sizes, and content
- Scan uploads if needed
- Authenticate and authorize WebSocket subscriptions
- Enforce timeouts and connection limits
12. Log and monitor
Log:
- auth failures
- unusual query patterns
- high-cost requests
- rate-limit hits
- schema errors
Avoid logging secrets or full sensitive payloads.
GraphQL-specific attack surfaces
Introspection abuse
Attackers can discover your full schema quickly.
Excessive nesting
A small query can cause huge backend work.
Field recursion / cyclic references
Even if schema recursion is legitimate, limits are needed.
Authorization bypass through nested fields
Example: user can fetch an object they’re allowed to access, then query sensitive nested relations that weren’t individually checked.
Denial of service
GraphQL can be abused via:
- deeply nested queries
- many aliases
- expensive resolvers
- subscription floods
Practical checklist
If you want a baseline secure setup:
- Authenticate all requests
- Enforce resolver-level authorization
- Add query depth and complexity limits
- Rate limit by user/token and query cost
- Use input validation/allowlists
- Protect cookies with CSRF defenses
- Disable or restrict introspection in public environments
- Log suspicious queries
- Test with malicious GraphQL payloads
- Review every new field for data leakage
Tools and framework support
Many GraphQL servers support security features through plugins/middleware, such as:
- Apollo Server plugins
- GraphQL Shield / authorization middleware
- Query complexity analyzers
- Persisted queries / allowlisted operations
Persisted queries can help a lot: clients can only execute pre-approved operations, which sharply reduces abuse.
If you want, I can also give you:
- a GraphQL security checklist for production, or
- code examples for Apollo Server, Yoga, or GraphQL.js.