Resource-Level Authorization
Role checks alone are often insufficient. Many applications need to determine whether the authenticated user can access a specific resource.
Consider:
mutation UpdateProfile($id: ID!, $input: UpdateProfileInput!) {
updateProfile(id: $id, input: $input) {
id
name
}
}
Suppose the authenticated user is user-10, but the requested profile belongs to user-20.
A simple CUSTOMER role check would not be enough. The server must verify ownership:
const profile = await profileService.findById(id);
if (profile.ownerId !== context.user.id) {
throw new Error("Forbidden");
}
This is resource-level authorization.
A more scalable policy might be:
authorization.canUpdateProfile(context.user, profile)
The policy can then consider multiple conditions:
- Is the user the owner?
- Is the user an administrator?
- Is the account active?
- Is the resource locked?
- Does the user's organization own the resource?
This type of authorization is especially important in multi-tenant applications where users from one organization must never access another organization's data.
Resource-Level Authorization
Key Takeaways
- Authentication alone does not protect individual resources.
- Resource ownership can be part of an authorization policy.
- Multi-tenant systems require strong tenant isolation.
- Authorization logic should be centralized enough to remain consistent.
Knowledge Check
Why is a role check alone insufficient for a customer updating a profile?