GraphQL's flexibility is an authorization problem in disguise
Field-level resolvers make it easy to forget who's allowed to ask what. Common GraphQL authorization failures and how to test for them.
Field-level resolvers make it easy to forget who's allowed to ask what. Common GraphQL authorization failures and how to test for them.
REST APIs fail authorization at the route level — miss a check, and one endpoint is exposed. GraphQL fails it at the field level, which means the same missing check can be reachable through a dozen different query shapes, some of which the team building the schema never anticipated.
The core issue is that GraphQL's resolver model encourages composing data access from small, reusable pieces — which is exactly what makes it powerful for frontend teams, and exactly what makes centralized authorization easy to get wrong. A resolver written to be 'just a data fetch' quietly becomes an authorization boundary the moment it's exposed in a schema that any authenticated client can query in combination with other fields.
Testing this manually means treating the schema itself as an attack map: enumerating every type and field, then asking — for each one — under what identity and permission level should this be reachable, and then actually querying it as a lower-privileged session to check. Introspection, when left enabled, does half this reconnaissance for you.
The most reliable fix I've seen teams adopt is authorization at the data-loader or service layer, not the resolver — so no matter which query shape reaches a given piece of data, the same check runs every time.