This guide is written by the team that builds Casdoor and describes the standards as published (listed under Sources), with notes on how Casdoor implements them as of November 1, 2026. Spotted a mistake? Tell us.
Scopes are how an OAuth client says what it wants to do, and how the user and the authorization server bound what a token can do. They are the primary tool for least privilege in OAuth — and the one most often designed badly.
This article covers how scopes work and how to design them.
What the specification says
In RFC 6749, a scope is a space-delimited list of case-sensitive strings. The authorization server defines the vocabulary; the client requests a subset; the user consents; the access token carries the granted scopes.
Two rules people miss:
- The server may grant fewer scopes than requested. The client must read the token's granted scopes, not assume.
- A refresh request may ask for a narrower scope set than the original grant (RFC 6749 §6). It must never widen it.
Scopes are permissions, not roles
A role is a bundle of permissions assigned to a person. A scope is a limit on what a client may do with a token.
adminis a role.users:readandusers:writeare scopes.
If you make admin a scope, every client that needs one admin action gets all of them, and the user consent screen says nothing useful. Keep roles in your authorization model (RBAC/ABAC) and scopes in the token.
Designing the vocabulary
Good scopes are:
- Resource-oriented:
orders:read, notgetOrders. - Coarse enough to be usable: one scope per resource and action class, not per endpoint.
- Stable: renaming scopes breaks existing grants.
- Documented: published with the API, with examples.
A practical pattern is resource:action with a small action set: read, write, delete, admin. For example: invoices:read, invoices:write.
Granularity trade-offs
Too coarse: a single api scope is effectively full access. One leaked token can do everything, and consent is meaningless.
Too fine: a scope per endpoint produces hundreds of strings, consent screens no one reads, and clients that ask for everything because they cannot tell what they need.
Aim for the smallest set that maps to user-visible capabilities.
The consent screen is part of the design
Users decide based on what you show them. Scope descriptions should be human sentences: "Read your invoices" rather than invoices:read.
If your consent screen lists twenty scopes, the design is wrong — either the scopes are too fine or the client is over-asking.
Resource indicators
RFC 8707 adds a resource parameter so a client can say which API the token is for. The authorization server then issues a token whose audience is that resource, instead of one token that works everywhere.
This matters in multi-service architectures: an access token for the billing API should not be accepted by the admin API. If your identity provider supports resource indicators, use them; if not, at least validate audiences per API.
Scopes and refresh tokens
- A refresh token inherits the original grant's scopes.
- A refresh request can reduce scopes, never increase them.
- If the client needs more later, it must send the user through a new authorization request.
Downscoping on refresh is a useful pattern for apps that need broad access once (for example, during setup) and narrow access afterwards.
Common mistakes
- One scope to rule them all.
apiorfull_accessdefeats least privilege. - Wildcards.
*in a scope string is impossible to reason about; avoid it. - Scopes that encode tenant or user IDs. Those belong in the token's claims or audience, not the scope list.
- Trusting the requested scopes. Always record the granted scopes with the token.
- No consent review. If the user cannot understand what they approve, the scope design has failed.
- Scopes as a substitute for authorization. A token that says
invoices:readstill needs a server-side check that this user may read this invoice.
How Casdoor handles scopes
Casdoor issues OAuth and OIDC tokens with scopes and supports per-application configuration, so each application can request only what it needs. OIDC adds the standard scopes (openid, profile, email) on top of your API vocabulary.
Related reading: OAuth grant types, what OAuth 2.0 is and API keys vs OAuth.
Sources
- RFC 6749: The OAuth 2.0 Authorization Framework (scopes)
- RFC 8707: Resource Indicators for OAuth 2.0
- OAuth 2.1 draft
- OpenID Connect Core 1.0 (scopes)
Product names are trademarks of their respective owners.