The OAuth 2.0 specification is a flexibile authorization framework that describes a number of grants (“methods”) for a client application to acquire an access token (which represents a user’s permission for the client to access their data) which can be used to authenticate a request to an API endpoint.
The specification describes five grants for acquiring an access token:
In this post I’m going to describe each of the above grants and their appropriate use cases.
As a refresher here is a quick glossary of OAuth terms (taken from the core spec):
The authorization code grant should be very familiar if you’ve ever signed into an application using your Facebook or Google account.
The client will redirect the user to the authorization server with the following parameters in the query string:
response_type
with the value code
client_id
with the client identifierredirect_uri
with the client redirect URI. This parameter is optional, but if not send the user will be redirected to a pre-registered redirect URI.scope
a space delimited list of scopesstate
with a CSRF token. This parameter is optional but highly recommended. You should store the value of the CSRF token in the user’s session to be validated when they return.All of these parameters will be validated by the authorization server.
The user will then be asked to login to the authorization server and approve the client.
If the user approves the client they will be redirected from the authorisation server back to the client (specifically to the redirect URI) with the following parameters in the query string:
code
with the authorization codestate
with the state parameter sent in the original request. You should compare this value with the value stored in the user’s session to ensure the authorization code obtained is in response to requests made by this client rather than another client application.The client will now send a POST request to the authorization server with the following parameters:
grant_type
with the value of authorization_code
client_id
with the client identifierclient_secret
with the client secretredirect_uri
with the same redirect URI the user was redirect back tocode
with the authorization code from the query stringThe authorization server will respond with a JSON object containing the following properties:
token_type
this will usually be the word “Bearer” (to indicate a bearer token)expires_in
with an integer representing the TTL of the access token (i.e. when the token will expire)access_token
the access token itselfrefresh_token
a refresh token that can be used to acquire a new access token when the original expiresThe implicit grant is similar to the authorization code grant with two distinct differences.
It is intended to be used for user-agent-based clients (e.g. single page web apps) that can’t keep a client secret because all of the application code and storage is easily accessible.
Secondly instead of the authorization server returning an authorization code which is exchanged for an access token, the authorization server returns an access token.
The client will redirect the user to the authorization server with the following parameters in the query string:
response_type
with the value token
client_id
with the client identifierredirect_uri
with the client redirect URI. This parameter is optional, but if not sent the user will be redirected to a pre-registered redirect URI.scope
a space delimited list of scopesstate
with a CSRF token. This parameter is optional but highly recommended. You should store the value of the CSRF token in the user’s session to be validated when they return.All of these parameters will be validated by the authorization server.
The user will then be asked to login to the authorization server and approve the client.
If the user approves the client they will be redirected back to the authorization server with the following parameters in the query string:
token_type
with the value Bearer
expires_in
with an integer representing the TTL of the access tokenaccess_token
the access token itselfstate
with the state parameter sent in the original request. You should compare this value with the value stored in the user’s session to ensure the authorization code obtained is in response to requests made by this client rather than another client application.Note: this grant does not return a refresh token because the browser has no means of keeping it private
This grant is a great user experience for trusted first party clients both on the web and in native device applications.
The client will ask the user for their authorization credentials (ususally a username and password).
The client then sends a POST request with following body parameters to the authorization server:
grant_type
with the value password
client_id
with the the client’s IDclient_secret
with the client’s secretscope
with a space-delimited list of requested scope permissions.username
with the user’s usernamepassword
with the user’s passwordThe authorization server will respond with a JSON object containing the following properties:
token_type
with the value Bearer
expires_in
with an integer representing the TTL of the access tokenaccess_token
the access token itselfrefresh_token
a refresh token that can be used to acquire a new access token when the original expiresThe simplest of all of the OAuth 2.0 grants, this grant is suitable for machine-to-machine authentication where a specific user’s permission to access data is not required.
The client sends a POST request with following body parameters to the authorization server:
grant_type
with the value client_credentials
client_id
with the the client’s IDclient_secret
with the client’s secretscope
with a space-delimited list of requested scope permissions.The authorization server will respond with a JSON object containing the following properties:
token_type
with the value Bearer
expires_in
with an integer representing the TTL of the access tokenaccess_token
the access token itselfAccess tokens eventually expire; however some grants respond with a refresh token which enables the client to get a new access token without requiring the user to be redirected.
The client sends a POST request with following body parameters to the authorization server:
grant_type
with the value refresh_token
refresh_token
with the refresh tokenclient_id
with the the client’s IDclient_secret
with the client’s secretscope
with a space-delimited list of requested scope permissions. This is optional; if not sent the original scopes will be used, otherwise you can request a reduced set of scopes.The authorization server will respond with a JSON object containing the following properties:
token_type
with the value Bearer
expires_in
with an integer representing the TTL of the access tokenaccess_token
the access token itselfrefresh_token
a refresh token that can be used to acquire a new access token when the original expiresThere are additional grants that have been published in other specifications that I will cover in a future article.
A grant is a method of acquiring an access token. Deciding which grants to implement depends on the type of client the end user will be using, and the experience you want for your users.
A first party client is a client that you trust enough to handle the end user’s authorization credentials. For example Spotify’s iPhone app is owned and developed by Spotify so therefore they implicitly trust it.
A third party client is a client that you don’t trust.
An access token represents a permission granted to a client to access some protected resources.
If you are authorizing a machine to access resources and you don’t require the permission of a user to access said resources you should implement the client credentials grant.
If you require the permission of a user to access resources you need to determine the client type.
Depending on whether or not the client is capable of keeping a secret will depend on which grant the client should use.
If the client is a web application that has a server side component then you should implement the authorization code grant.
If the client is a web application that has runs entirely on the front end (e.g. a single page web application) you should implement the password grant for a first party clients and the implicit grant for a third party clients.
If the client is a native application such as a mobile app you should implement the password grant.
Third party native applications should use the authorization code grant (via the native browser, not an embedded browser - e.g. for iOS push the user to Safari or use SFSafariViewController, don't use an embedded WKWebView).