Secure your API — identify the caller once in the context, then enforce permissions inside resolvers and at the field level, where authorization actually belongs.
Why: the context function runs once per request, before resolvers — the right place to read the auth token from the HTTP headers, verify it, and attach the user. Every resolver then sees ctx.user. Authentication (who are you?) happens here, once.
await startStandaloneServer(server, {
context: async ({ req }) => {
const token = req.headers.authorization?.replace('Bearer ', '')
const user = token ? await verifyToken(token) : null
return { user }
},
})Note: because GraphQL has one endpoint, you cannot secure it with per-route URL rules like REST. Security lives in the schema and resolvers instead. Also guard against abuse the open graph enables: limit query DEPTH and COMPLEXITY so a deeply nested query cannot become a denial-of-service. Libraries exist for both.
REST: secure each URL/route
GraphQL: one endpoint → secure in resolvers + the schema
also add: query depth limit + complexity limit (anti-DoS)