Implementing GraphQL Security

1. Protecting Against Query Abuse

DefenseDetail
Depth limitPrevent recursive nesting attacks
Complexity limitCost-based budget
Rate limitPer IP and per user
Pagination capMax first/last = 100
Timeout30s hard cap

2. Implementing Query Whitelisting

Example: Persisted-only mode

plugins: [usePersistedOperations({
  getPersistedOperation: (hash) => allowlist.get(hash),
  allowArbitraryOperations: false  // reject anything not in allowlist
})]

3. Preventing Schema Leakage

PracticeDetail
Disable introspection in prodDefense in depth
Suggestion blockingDisable "Did you mean…" hints
Mask error stacksStrip in production formatter
Persisted queriesBest protection — schema-as-API hidden

4. Validating Input Data

LayerDetail
SchemaCustom scalars (Email, URL) reject malformed early
ResolverZod / Joi for business rules
DBConstraints as last line of defense

5. Implementing CSRF Protection

Example: Apollo CSRF prevention

new ApolloServer({
  csrfPrevention: true  // requires apollo-require-preflight or non-simple Content-Type
});
DefenseDetail
Preflight requiredForce CORS preflight to validate origin
SameSite cookiesLax/Strict prevents cross-site auth
Avoid GET mutationsSpec already forbids; enforce in router

6. Securing WebSocket Connections

PracticeDetail
wss:// onlyTLS for all subscription traffic
Auth in connectionParamsValidate at connection_init
Origin checkReject foreign origins
Heartbeat / pingDetect dead connections
Per-connection rate limitCap subscriptions per session

7. Implementing API Key Authentication

Example: API key middleware

context: async ({ req }) => {
  const key = req.headers["x-api-key"];
  if (!key) throw new GraphQLError("Missing API key", { extensions: { code: "UNAUTHENTICATED" } });
  const client = await db.apiKey.findUnique({ where: { hash: sha256(key) } });
  if (!client || client.revokedAt) throw new GraphQLError("Invalid key", { extensions: { code: "UNAUTHENTICATED" } });
  return { client };
}

8. Using TLS/HTTPS

SettingDetail
TLS 1.2+Disable older protocols
HSTSStrict-Transport-Security: max-age=31536000; includeSubDomains
HTTP → HTTPS redirectForce upgrade
mTLSService-to-service inside mesh

9. Auditing Security Vulnerabilities

ToolDetail
npm audit / pnpm auditDependency CVEs
Snyk / DependabotAutomated PRs
Inql / GraphQL CopGraphQL-specific scanners
OWASP ZAPActive scanning

10. Following OWASP Guidelines

OWASP API Top 10 RiskGraphQL Mitigation
BOLA (auth)Field-level authz; verify ownership
Broken authnStrong JWT validation, key rotation
Excessive data exposureDon't expose sensitive fields publicly
Resource exhaustionDepth + complexity + rate limits
Mass assignmentExplicit input types only
InjectionParameterized queries, never string-concat user input
Improper inventorySchema registry; deprecate old fields