Pablo Cibraro

My notes about software development, security and other stuff.

Roles and Scopes in OAuth 2.0

Roles and Scopes are two different mechanisms for implementing authorization in Web APIs with OAuth 2.0.

While scopes are part of the OAuth 2.0 specification, Roles are not. The later are still leveraged by some authentication platforms like Azure AD or Auth0, which made them available as part of the access tokens (JSON Web Tokens or JWT).

Roles represent an old school concept for authorization. They give permissions for performing actions on a given resource/web api (e.g permissions for deleting emails). A system administrator is who assigns roles to users or other participants in the system (they are not requested). For example, Azure AD allows role assignment to users or groups. When access tokens are issued for a Web API, they contains all the user roles for that particular API. The Web API can later check those roles for performing authorization.

The following sample shows how Azure AD includes roles in a JWT,

{
  "iss": "<azuread>",
  "aud": "http://myapi.com",
  "roles": ["Administrator"]
}

One of the disadvantages with Roles is that all users in a system must be known in advance and assigned with the right permissions. This does not scale well for Open APIs that can be used for thousand of users. Clear examples of that are social media APIs such as Facebook, Twitter or Google to name a few.

Scopes represent a different approach for authorization. With scopes, the resource owner (e.g. web API owner) publishes a set of supported scopes representing permissions on that particular resource (e.g. admin, read or write).

Client applications acting on behalf of the resource's owner (the user) can request the use of one or more scopes, which must be approved or granted.

If we consider Google APIs for example, emails and contacts are resources, which have an owner (the user). Google offers different scopes for performing actions around them such as read or write emails, or create contacts. The user can approve any client application to read his emails but not other people's email (as he/she does not own those) by granting the "email read" scope to those applications. Similarly, users can only approve the "email read" scope but not the "contacts read" scope, which will prevent that client application to read any contact from the user.

Scopes are initially included in the request for an access token to an authorization server as it shown below,

client_id=...&
client_secret=...&
scope=reademail writecontact&
username=...&
password=...&
grant_type=password

Once this request is approved, the resulting access token or JWT will contain the approved scopes.

{
"iss": "<azuread>",  
"aud": "http://myapi.com",  
"scopes": ["reademail", "writecontact"]
}

By using scopes, the designer of an API must first define resources, boundaries (who is the owner) and the actions that can take place on those boundaries (scopes). Client applications will eventually request them on demand. No previous assignment of permissions is required before hand to get that model working.