Scopes Explained
On this page
Scopes and their relation to claims
In this article we take a closer look at scopes and discuss how to handle them properly.
What are Scopes?
A scope is simply a grouping of claims, although the name sometimes lends itself to other interpretations. You can think of claims as access ranges or "scopes of access". Depending on whether you use OAuth or OpenID Connect, scopes are are to a greater or lesser degree defined.
OAuth defines scopes in a very open and forgiving way. In OAuth, a scope is a string that may represent a resource the Client requests access to.
In OpenID Connect, however, a scope is defined in a more clear-cut manner, and the specification even defines pre-defined scopes that have meaning in the OpenID Connect context.
Claims are not part of OAuth but are added in OpenID Connect. Therefore, it is only the OpenID Connect specification that maps pre-defined claims to pre-defined scopes.
Default scopes
The OpenID Connect specification only defines a single set of standard scopes:
Scope | Claims |
---|---|
email, email_verified | |
address | address |
profile | name, family_name, given_name, middle_name, nickname, preferred_username, profile, picture, website, gender, birthdate, zoneinfo, locale, updated_at |
phone | phone_number, phone_number_verified |
openid | sub, auth_time, acr |
The anatomy of scopes
The scope
request parameter is a space separated, case-sensitive list of scopes. So it may contain several scopes, even though the singular parameter name may suggest otherwise.
The specification defines formats and server handling but does not prescribe any particular contents or behaviors beyond that. This means that it is very easy to customize your own scope architecture. It also means that you should customize with care.
Scopes in tokens
Scopes are only present in OAuth Access Tokens. The ID Token never contains scopes but instead contains the resolved claims that belong to the issued scopes. This is an important difference. The ID Token is intended to be used and read by the Client, while the Access Token is intended to be read and understood by the API. The Access Token should be treated as opaque to the Client.
This means that the Scopes in the Access Token may be used as coarse-grained access control attributes.
Example
An API defines an invoice service with two main operations: read and write. Some Clients only need read access so end-users can view their invoices, while other Clients need write access for the internal Clients that create the invoices.
A scope and claim pattern could look as follows:
Scope | Associated Claims |
---|---|
read | customer-number |
write | customer-number, invoice-center |
When a read Client requests an access token, the claim customer-number
will be added and populated with the customer number associated with the invoices to be shown (given that claims are mapped to the access token). The token also contains the scope=read
string.
When a write Client requests access, the claim invoice-center
is also added to the token with a value indicating the department the invoices are handled from. The scope write
is also part of the access token.
This provides some benefits, as it is now possible to provide different degrees of access control when the API call is made. More on that in the following sections.
Requesting scopes
When requesting scopes, make sure that your applications only ask for what they need. If all you want to do is identify a user, don't request more than you need to assert it. Consider the use case and select accordingly.
Default or fail
Make sure to request something or be prepared for the consequences. According to the specification, if a scope is not specified in the request, the server can either return a default scope, something else, or completely fail the request.
It is also possible to request only single claims, even from different scopes, if that is what the application needs and no more. Remember, the point is to be as exclusive as possible.
This also affects consent. When you only request what you need, you are more likely to gain user consent since users are more likely to grant access for limited, clearly specified scopes of access.
Scopes and claims in use
When used in the authorization flows, the client sends an authorize request, including the scope or scopes or specific claims it needs (and ideally, only those it needs) to the OpenID Connect provider. This eventually results in the issuance of one or many tokens, which contains claims according to the requested scopes.
Claims, not scope
If the request is for less than the full scope, the returned token contains a list of claims, and does not include the scope itself.
Receiving scopes
When users provide consent, they may not be intending to grant consent to everything, and the application may request scopes that the user has not consented to.
In such cases, the server overrides the scope request and does not provide what was asked for. However, the server must still include the scope in its response, informing the client what scope was actually issued.
Therefore, it is important that the application requesting a scope (or claim) has a process in place for how to respond when what was requested is not what was received. This may include asking for additional consent, informing the user about reduced functionality, or perhaps requiring a complete re-authorization.
Using scopes for Authorization
When the client makes a request to the API, it is now possible to make a coarse-grained authorization decision in a gateway. The gateway checks if the token is valid by communicating with the Token Service to validate the token. If using the Phantom Token Flow, the Token Service responds with a JWT representation of the same token. The gateway can then check if any of the required scopes is present in the token.
In the example above, this means, for the Invoice API, either read
or write
needs to be present. The gateway doesn't need to check if the depth of the operation matches the scope. That is, that it is left for the API to resolve later, but the gateway can stop unwanted requests early on, at a low cost. This keeps the complexity of the gateway to a minimum but provides a robust layer of authorization in front of the API.
The API will obviously be required to check that the operation matches the scope required and that the claims it needs are present. But this is then part of a more fine-grained authorization decision.
Scope explosion
One problem that may occur when using scopes stems from an intuitive but incorrect way of thinking about what scopes are. We call this problem scope explosion: the proliferation of scopes beyond the point of manageability.
This normally occurs when an enterprise tries to address the need for multiple roles by using scopes as a sort of role identifier instead of using claims to take a more fine-tuned approach.
To avoid scope explosion, it is best not to attach scopes to users. Doing so necessitates new roles for each application, sometimes even multiple roles for each user, leading to an non-scalable and unmanageable "explosion" of scopes, including overlaps and redundancies.
The Prefix Scope
Curity has a special type of scope called the Prefix Scope. As the name suggests, the scope itself is just a prefix and the final scope depends on what the client requests.
Example
Prefix Scope: read-
Requested Scope: read-diary
Issued Scope: read-diary
The prefix scope is useful when there are resources that need to be allocated dynamically. The server can implement policies to issue or not to issue these scopes as needed.
If consent is enabled, the user will be presented with a suffix, diary
in the above example, to consent to.
A prefix scope cannot carry any claims. Instead the value of the suffix is considered to be a claim of sorts, which is why this is a matter of consent.
An example of this is when the user needs to consent to a transaction. The prefix transaction-
can be used with an ID added transaction-100.311
to show the user what is going on.
If the exact scope is present, the API can then allow access to particular resources.
Prefix Scopes and Claims
A prefix scope cannot be mapped to any additional claims. This would result in the scope itself being consented to.
The Curity Solution
Curity provides the full benefits of OAuth and OpenID Connect standards, but also offers additional functionality to combat the risk for scope explosion.
There is also special handling of claims and scopes, such as mapping claims to specific clients and custom groupings that allow for greater flexibility and a more manageable architecture.
More information
For more information, see the mentioned articles above, or the Curity Developer Portal
Curity
Join our Newsletter
Get the latest on identity management, API Security and authentication straight to your inbox.
Start Free Trial
Try the Curity Identity Server for Free. Get up and running in 10 minutes.
Start Free Trial