Quick answer
OAuth scopes are permission labels attached to an access token. They describe what the token is allowed to do, such as reading orders, writing invoices, or managing webhooks.
Scopes are useful for least privilege, consent screens, API authorization, and safer integrations. They are not useful unless the resource server validates them before allowing protected actions.
A scope is a claim. Enforcement is backend code.
What a scope looks like
Scopes are often represented as strings:
orders:read
orders:write
invoices:read
profile:email
webhooks:manage
An access token may include one or more scopes.
In a JWT, scopes may appear in a scope claim, an scp claim, or a provider-specific claim:
{
"sub": "user_123",
"aud": "orders-api",
"scope": "orders:read invoices:read",
"exp": 1793551200
}
The exact claim name and format depend on the authorization server. The resource server must know what to expect.
Scopes vs roles
Scopes and roles are related, but they are not the same thing.
| Concept | Typical meaning |
|---|---|
| Scope | What this token is allowed to do. |
| Role | What this user or service is within a system. |
| Permission | A lower-level allowed action. |
| Policy | Logic that combines caller, resource, action, and context. |
A user may be an admin, but a specific access token might only have orders:read. That is useful because a token can be narrower than the user’s full account rights.
Read RBAC vs ABAC for role and attribute tradeoffs.
Scopes and consent
In user-delegated OAuth flows, scopes often appear on consent screens.
A user might see that an app requests:
Read your profile
Read your invoices
Manage your webhooks
The user is not granting every possible permission. They are granting a bounded set of capabilities to a client application.
For internal service-to-service flows, there may be no human consent screen, but scopes still define what the client credential can access.
Scope naming
Good scope names are understandable, stable, and enforceable.
Common patterns:
resource:action
orders:read
orders:write
customers:read
webhooks:manage
Avoid vague scopes:
api
full
basic
premium
Vague names make authorization reviews harder. They also make it difficult to explain risk to users, partners, and internal teams.
Read and write scopes
A common baseline is to separate read and write actions.
orders:read
orders:write
This lets a reporting integration read orders without changing them.
Some APIs need more specific actions:
payments:create
refunds:create
customers:delete
api_keys:rotate
The right granularity depends on risk. High-impact actions deserve narrower scopes.
Scopes are not tenant checks
A scope says what action is allowed. It does not automatically say which resource belongs to the caller.
For example:
orders:read
This scope should not allow reading every order in every tenant. The backend still needs ownership, tenant, account, or organization checks.
valid scope + wrong tenant = deny
This is where authorization design matters. Read Authorization vs Authentication for the boundary.
Resource server validation
The API that receives the access token is the resource server. It must validate both token trust and token permission.
A protected endpoint might require:
GET /orders -> orders:read
POST /orders -> orders:write
POST /webhooks -> webhooks:manage
Validation should include:
- Signature or introspection result.
- Issuer.
- Audience.
- Expiration.
- Subject.
- Scope or permission claim.
- Tenant or resource ownership.
Read API Authentication Best Practices for the broader checklist.
Scopes in service-to-service APIs
In the client credentials flow, a service obtains a token for itself, not for a user.
That token should still be scoped.
For example, a billing worker might get:
invoices:read invoices:write
It should not automatically receive:
users:delete admin:all
Read OAuth Client Credentials Flow Explained for the service-to-service pattern.
Scopes and JWT claims
Scopes are often only one part of token authorization.
Other useful claims may include:
subfor the subject.audfor the intended API.issfor the issuer.expfor expiration.client_idfor the client application.tenant_idor organization context.- Roles or permissions.
Read JWT Claims Explained before trusting a token’s contents.
Common mistakes
The first mistake is checking only that a token exists. A token without the required scope should not pass.
The second mistake is treating a broad admin scope as a shortcut for every integration.
The third mistake is using scopes as tenant checks. Tenant and ownership checks are separate.
The fourth mistake is renaming scopes casually. Clients may depend on them, and documentation may become stale.
The fifth mistake is putting sensitive data into scope names. Scope strings often appear in logs, dashboards, and consent screens.
Practical scope checklist
When designing scopes:
- Name scopes by resource and action.
- Start with read/write separation.
- Use narrower scopes for destructive or financial actions.
- Document required scopes per endpoint.
- Validate scopes in the resource server.
- Combine scopes with tenant and ownership checks.
- Avoid broad default scopes.
- Keep scope names stable over time.
- Test missing-scope and wrong-scope failures.
- Return clear
403 Forbiddenresponses when permission is denied.
Scopes are a vocabulary for authorization. They become security only when the backend enforces them consistently.
Related reading
Read OAuth 2.0 Explained for Backend Developers for the full OAuth model, OAuth Client Credentials Flow Explained for service tokens, and JWT Claims Explained for token claim validation. Read Least Privilege Explained, RBAC vs ABAC, and API Authentication Best Practices for protected API design. For the guided sequence, browse the Authentication Learning Path, Backend Security Learning Path, and Topics.