Some notes on OAuth2.0
OAuth2 is an authorization protocol primarily used for granting access to user resources to a third party application. However, it is also often misused as a pseudo authentication protocol, simply to identify a user.
Let’s assume we want to write a Facebook application that lists all of a user’s friends by their most recent posts.
Roles
OAuth2 defines 4 different roles:
- Resource Owner:
This is the user whose data we want to access. The resources are the user’s data, such as their list of friends and their public posts. Note that the Resource Owner doesn't actually have to be a human user but can also be an application. - Resource Server:
This is the server on which the user’s resources are stored. In our scenario, this would be a Facebook server (several probably). - Authorization Server:
This is the server that verifies the identity of the user and handles authorization of the third party applications that want to access a Resource Owner’s data on the Resource Server. OAuth2 allows the Resource and the Authorization Server to be the same server, which is why from the point of view of the developer these two can also be described as service or API. - Client: This is the third party application that is requesting access to the user’s data on the Resource Server. In our scenario, that would be the application we are writing.
Basic Protocol Flow
OAuth2 also defines four different grant types for authorizing Client Applications. Before introducing the grant types though, let’s look at the general communication flow of the OAuth2 protocol.
- Client application is registered:
Before authorization requests can be made, the Client application must be registered at the Resource Server’s platfom. During registration the developers have to provide information, such as the name of the application and a redirect url, the purpose of which will be explained later. Once the Client Application is registered, it receives a client ID to uniquely identify a Client Application among all other applications and a client secret, which the Client App uses to authenticate itself when making requests to API requests. In our scenario, we would register our app at the Facebook Developer Center. - Client App asks user for authorization: The Client Application now must ask the user for authorization to their resources, which is usually done by presenting a link, that redirects the user to the Authorization Server. This link includes the client ID, identifying the Client App to the Authorization Server. This link or button could be listed on our client site stating click here to list your Facebook friends by post frequency.
- User Authorizes the Client App: Once the user clicks the link, their browser will redirect them to the Authorization Server. The Authorization Server will ask the user whether they wish to authorize the Client Application to access their data and also list the scope of authorization (read or read write etc.) that the Client App wishes to receive.
- User authorizes Client App:
Once the user authorizes the Client App's request to access their resources, the Authorization Server sends an authorization grant to the Client Application. - Client requests Access Token from Authorization Server:
With the Authorization Grant received from the Resource Server in the previous step, the Client Application now request an access token from the Authorization Server. To receive the access token, the Client must now authenticate itself by including its client ID and client secret in the request to the Authorization Server. - Client receives access token:
If the Client has provided a valid Authorization Grant and also correctly authenticated itself to the Authorization Server, it will receive an access token and potentially also a refresh token. - Client makes resource request to the Resource Server:
Now that the Client has an access token, granting it access to the user’s resources within the specified scope, it can request user’s resources from the Resource Server. Every such request must include a valid access token. If the access token has expired and the Client has a refresh token, it can request a new access token by providing its refresh token to the Authorization Server.
Grant Types
OAuth2 also defines four different grant types for authorization. Those are:
Authorization Code:
The Authorization Code grant type is commonly used with server side applications. That is, applications whose main code is stored on a server to which the public does not have access. The exact protocol flow for the Authorization Code pretty much follows the general protocol flow described above. The Client App redirects the user to the Authorization Server, providing all necessary information in the request URL. The following parameters are included in the query string that redirects the user to the authorization server:
response_type=code
: This tells the Authorization Server that the Client is expecting an authorization code in response, should the user authorize the Client Applicationclient_id=[client ID]
redirect_uri=[a URI]
: This optional parameter is the URI to which the user will be redirected, after they authorize the Client. If omitted, the user will be redirected to the URI that was specified when registering the Client Application.scope=[list of scopes]
:The value of this optional parameter is a space delimited list of scopes. Some Facebook example scopes are:email
,read_stream
oruser_actions.video
state=[random string]
: Optional. This is simply a random string used to protect against CSRF attacks.
Once the user authorizes the Client Application, the Authorization Server will redirect the user’s browser to the specified redirect URI, including the authorization code and the state query parameter in case the Client provided one.
Next, the Client sends a POST request back to the Authorization Server including the following query parameters:
grant_type=authorization_code
client_id=[client ID]
client_secret=[client secret]
redirect_uri=[URI]
code=[received auth code]
: This is the authorization code the Client received from the Authorization Server
The Authorization Server responds to this POST request with a JSON object containing the following properties
token_type: Bearer
: Meaning that the bearer of this token is to be granted access to the resources.expires_in
: An integer representing the TTL of the access tokenaccess_token
: The access tokenrefresh_token
: Encrypted payload that can be used to receive a new access token after the old one has expired
Now the Client can make requests to the Resource Server, providing the access_token
it received from the Authorization Server
Implicit:
The Implicit Grant flow is simpler than the Authorization Code grant type. It is commonly used when there is no server on which a client secret can be stored. This is the case when the Client Application is user-agent based, as are for instance, mobile apps or single page web apps. Another difference between the Implicit Grant type and the Authorization Code grant type is that the Authorization Server immediately returns an access_token rather than an authorization_code. Also, the Implicit Grant type does not return a refresh token.
The Client redirects the user to the Authorization Server, with the request parameter value of token
. The other request parameters are the same as in the Authorization Code case.
Once the User authorizes the Client the Authorization Server redirects the User back to the Client using the redirection URI provided earlier. The redirection URI now also includes the access token in the fragment of the URI.
The User Agent executes the redirect instructions by making a request to a Web-Hosted Client Resource at the given redirect URI. However, as per RFC2616, the fragment isn’t sent to the Web-Hosted Client Resource and is instead retained by the User Agent.
As a response to the request the Web-Hosted Client Resource returns a web page, typically some HTML with an embedded script capable accessing the full redirection URI retained by the User Agent and extracting the access_token and other parameters contained in the fragment.
The User Agent executes the provided script extracting the access_token and the other information provided in the fragment. Finally the User Agent passes the access token to the Client.
This grant type is called implicit, because the Web-hosted Client Resource at the redirection URI that returns the script that extracts the access token is ostensibly controlled by the same people who registered the third party application in the beginning
The Client never explicitly authenticates itself, since it can’t store a client secret (Note how it never sends a client secret to the authorization server). It is only implicitly authenticated by controlling the Web-Hosted Client Resource at the URI provided during registration of the Client Application.
Resource Owner Password Credentials:
The Resource Owner Password Credential grant type is generally only used when the Resource Owner has complete trust in the Client, as the Resource Owner provides their credentials (username and password) directly to the Client. This grant type is also commonly used as alternative authentication to HTTP Basic or Digest. Since this grant type bears many risks and relies on a lot of trust in the Client Application it is commonly not offered by many OAuth2 APIs.
The Client presents a form prompting the User to enter their username and password.
The Client requests an access token from the Authorization Server by providing both the User’s username and their password as query parameters in their authorization request to the Authorization Server. The grant_type parameter has the value password
. The Client also provides its client ID and client secret, authenticating itself to the Authorization Server.
The Authorization Server responds with a JSON object containing the same response as in the Authorization Code grant type.
Client Credentials:
The Client Credentials grant type is used to access resources on the Resource Server which are not tied to any specific user. For instance, retrieving the number of users currently registered at Facebook could be provided by Facebook under a Client Credentials grant type, as it doesn’t require any User to give permission to their own resources.
The client sends a POST request with the value client_credentials
as the grant_type
parameter. Additionally the Client provides their client ID and client secret, authenticating itself to the Authorization Server along with a space-delimited list of scopes in the scope
parameter.
The Authorization server returns a JSON object including the token_type
Bearer
along with the access_token
and the TTL in the expires_in
property.