Field-Level Authorization
You'll learn to
- -Enforce authorization at the individual field level, not just at the top-level query, since GraphQL lets one query touch many fields with different sensitivity
- -Decide what a field should return when the requester is not authorized to see it: null, an error, or the field omitted entirely
REST authorization is usually checked once, at the endpoint level - can this caller hit `GET /users/42` at all? GraphQL breaks that assumption: one query can touch dozens of fields across many types in a single request, and different fields on the same type can legitimately need different authorization rules for the same caller.
Why Endpoint-Level Auth Isn't Enough
query {
user(id: "42") {
name # public - anyone can see this
email # only the user themselves, or an admin
ssn # only an admin, and only with a specific audit-logged reason
}
}A single "can this caller query the `user` field at all" check can't express that `name`, `email`, and `ssn` on the exact same `User` object need three different authorization rules for the same caller - that granularity has to live at the individual field's resolver, not at the query root.
Enforcing Authorization in the Resolver
def resolve_email(user, info):
requester = info.context["current_user"]
if requester.id != user.id and not requester.is_admin:
raise GraphQLError("Not authorized to view this field")
return user.emailThe Three Ways to Handle an Unauthorized Field
- -Return null: the field exists in the schema for everyone, but resolves to null for an unauthorized caller. Simple, but conflates "you can't see this" with "this is genuinely empty," which can be ambiguous to the client.
- -Raise a field-level error: GraphQL supports partial responses - other fields in the same query can still succeed while one field reports an error, giving the client an explicit, unambiguous signal for that specific field.
- -Omit the field from the schema entirely for this caller (a fully role-based schema): the most restrictive option, appropriate when even the field's existence shouldn't be discoverable by unauthorized callers.
A field-level error is usually the clearest choice for genuinely sensitive fields, since it distinguishes "you're not allowed to see this" from "this value happens to be empty" - a distinction that matters a lot for something like `ssn`, where a `null` could mean either "not authorized" or "this person genuinely has no SSN on file," and a client (or a human reading a support ticket) has no way to tell which.
GraphQL's partial-response model means a query can return a 200 with some fields successfully populated and others reporting errors, all in the same response - client code needs to check per-field errors, not just assume "status 200 means everything I asked for came back."
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Design Permission Matrix in the API Design Lab's GraphQL Mastery act.