02.04 / 65 min

Test GraphQL authorization

Compare secure and vulnerable GraphQL fields while accounting for GraphQL’s common 200-with-errors behavior.

By the endUse GraphQL variablesInterpret data and errors semanticallyDetect field-level BOLA
Controlled exercise

Use only the Academy Lab on 127.0.0.1:5177. Do not copy these tests to a public system without explicit written authorization.

01

Build the secure query

Set POST /graphql, Content-Type application/json, select User A, and place the foreign object in variables.id.

{"query":"query Resource($id: ID!) { resource(id: $id) { id owner note } }","variables":{"id":"resource-b"}}
Expected result

HTTP 200 with data.resource null and an errors entry containing FORBIDDEN.

02

Switch to the vulnerable field

Change only resource to resourceInsecure and rerun the authorization matrix with User A and User B.

{"query":"query Resource($id: ID!) { resourceInsecure(id: $id) { id owner note } }","variables":{"id":"resource-b"}}
Expected result

HTTP 200 with User B’s resource data returned to User A.

03

Normalize dynamic fields

Exclude timestamps, trace identifiers, and session identifiers from comparison. Keep owner, tenant, note, GraphQL errors, and returned field paths in scope.

04

Confirm a second object

Run the vulnerable query again with resource-a under User B. Save both object results in one finding only when the behavior is the same.

MASTERY CHECKPOINT

Prove it before moving on.

You can explain why secure and vulnerable GraphQL responses both use HTTP 200 but have opposite authorization meanings.