The OAuth 2.0 Flows – Part I
The OAuth 2.0 framework is a delegation protocol specifically designed for authorization workflows. In this post, we will try to understand different flows (OAuth grant types) for clients to obtain the authorization grant.
OAuth 2.0 Roles and Terminologies
Let us revisit few important OAuth terminologies and entities involved in the workflows. OAuth defines four major roles –
- Resource owner is an entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.
- Resource server is the server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
- Client is an application making protected resource requests on behalf of the resource owner and with its authorization. The term “client” does not imply any particular implementation characteristics (e.g. whether the application executes on a server, a desktop, or other devices).
- Authorization server is the server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization. The authorization server may be the same server as the resource server or a separate entity. A single authorization server may issue access tokens accepted by multiple resource servers.
Let us also briefly understand few more important OAuth terminologies.
- Access tokens are credentials used to access protected resources. An access token is a string representing an authorization issued to the client. The string is usually opaque to the client meaning . Tokens represent specific scopes and duration of access, granted by the resource owner, and enforced by the resource server and authorization server.
- Refresh tokens are credentials used to obtain access tokens. Refresh tokens are issued to the client by the authorization server and are used to obtain a new access token when the current access token becomes invalid or expires. If the authorization server issues a refresh token, it is included when issuing an access token itself. Unlike access tokens, refresh tokens are intended for use only with authorization servers and are never sent to resource servers.
- HTTP Redirections – OAuth 2.0 specification makes extensive use of HTTP redirections, in which the client or the authorization server directs the resource owner’s user-agent (browser) to another destination.
- Client Registration is the process through which client is registered with authorization server. This happens before initiating the protocol typically by filling up HTML registration form by end user. While registering a client, client developer specifies client type, redirect URI, application name etc. required by authorization server.
- Client Types – Based on their ability to authenticate securely with the authorization server (i.e. ability to maintain the confidentiality of their client credentials), OAuth defines two Client Types.
- Confidential clients are those capable of maintaining confidentiality of their credentials, e.g. client implemented on a secure sever with restricted access to the client credentials
- Public clients are not capable of maintaining the confidentiality of their credentials, e.g. client executing on the device used by the resource owner such as an installed native app or a browser-based application.
- Client ID and client secret: Once your application is registered, the service will issue client credentials in the form of a client identifier and a client secret. The client ID is a publicly exposed string that is used by the authorization server to identify the application, and is also used to build authorization URLs that are presented to users. The client secret is used to authenticate the identity of the application to the authorization server when the application requests to access an user’s account, and must be kept private between the client application and the server.
- User Agent is the application used by the resource owner to interact with the client, for example a browser or a native application.
- Authorization grant – The authorization is expressed in the form of an authorization grant which in turn is used by the client to get access token. In simple words, an authorization grant is a credential (representing resource owner’s authorization to access its protected resources) used by the client to get ab access token.
OAuth defines four grant types which we will try to understand one by one. Sometimes these grants are also referred as flows, e.g. authorization code flow.
1. Authorization code grant
This grant type is the most commonly used because it is optimized for server-side applications, where source code is not publicly exposed, and client secret confidentiality can be maintained.
If you have signed into a third party application using your Facebook or Google account, you are familiar with this type. It is used to obtain both access tokens and refresh tokens and is optimized for confidential clients.
Since this is a redirection-based flow, the client must be capable of interacting with the resource owner’s user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.
- The client will construct the request URI and redirect the user to the authorization server with the following parameters in the query string:
response_type
with the valuecode
(Required)
client_id
with the client identifier (Required)redirect_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. (Optional)scope
a space delimited list of scopes (Optional)state
(Recommended). An opaque value used o maintain state between the request and callback. The authorization server includes this value when redirecting the browser back to the client. This should be used for preventing cross-site request forgery.
For example, the client directs the user-agent to make the following HTTP request using TLS:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
- 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 authorization server back to the client (redirect URI) with the following parameters in the query string:
code
with the authorization code generated by the authorization server (Required). Authorization code shall have shorter lifetime (max 10 minutes recommended) to avoid risk of leaks. It should not be used more than once and is bound to the client identifier.state
is required if ‘state’ parameter was sent in the original client authorization 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.
For example, the authorization server redirects the user-agent by sending the following HTTP response:
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA &state=xyz
If the request fails due to a missing, invalid, or mismatching redirection URI, or if the client identifier is missing or invalid, the authorization server should inform the resource owner of the error and must not automatically redirect the user-agent to the invalid redirection URI.
If the resource owner denies the access request or if the request fails for reasons other than a missing or invalid redirection URI, the authorization server informs the client by adding the error parameters to the query component of the redirection URI with appropriate error code.
Let’s skip error scenarios for this topic and assume user clicks ‘authorize’ button from the consent form.
- The client will now make a request to the token endpoint of the authorization server with the following parameters:
grant_type
with the value ofauthorization_code
(Required)code
with the authorization code received from the authorization server (Required)client_id
with the client identifier (Required)client_secret
with the client secret (Required)redirect_uri
with the same redirect URI the user was redirect back to
- If the access token request is valid and authorized, the authorization server issues an access token (and optional refresh token) and 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 indicating when the token will expireaccess_token
the access token itselfrefresh_token
a refresh token that can be used to acquire a new access token when the original one expires
An example of a successful response: HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"bearer", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }
Authorization code grant is best suited for server side applications. If the client is a regular web app executing on a server, then this is the flow you should use. It’s considered the safest choice since the Access Token is passed directly to the web server hosting the Client, without going through the user’s web browser and related risk.
As this post is now becoming longer than expected, we will talk about remaining types of authorization grants in our next article (Part-2).
Stay Safe, Stay Secure!