is
2019/08/26
 
26 Aug, 2019

OAuth 2.0 Basics

  • Ishara Karunarathna
  • Associate Technical Lead - WSO2

In my previous article “Say Hello to OAuth 2.0” I discussed about concepts and main actors behind OAuth 2.0 framework. Idea of this article is to get familiar remaining bits and pieces, mainly this article It’ll discuss different flows (grant types) that can be used to get an access token and recommendation on choosing grant types.

Quick Refresher — OAuth 2.0 Concepts

  • Resource owner: 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: The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
  • Client: An application making protected resource requests on behalf of the resource owner and with his 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: The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization.
  • Access tokens: 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. Tokens represent specific scopes and duration of access, granted by the resource owner and enforced by the resource server and authorization server.
  • Refresh Token: Refresh tokens are the 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, or to obtain additional access tokens with identical or narrower scope.
  • Scope: The level of access that the application is requesting. The authorization server may fully or partially ignore the scope requested by the client, based on the authorization server policies or the resource owner’s instructions.

Register Client with the Authorization Server

Prior to getting an access token, a trust relationship should be established between the client application and the authorization server. The client application has to be registered in the authorization server to initiate this trust relationship. There are two common ways used to register an application.

  1. Use dynamic client registration (DCR) API
  2. Manually create a client application in the authorization server (using admin console or CLI tool)

In general for registered clients, the authorization server will issue a client ID and client secret.

  • Client id: String value that uniquely identifies the client application in the authorization server.
  • Client secret: This is a secret value that can be used with client id to authenticate with the authorization server (if client secret is used client application should be able to protect it in application end).

OAuth 2.0 Protocol Endpoints

There are two endpoints in the authorization server used in obtaining an access token:

  • Authorization endpoint — used by the client application to obtain an authorization grant from the resource owner via user-agent redirection.
  • Token endpoint — used by the client application to exchange an authorization grant for an access token, typically with client authentication.

And there is a client endpoint:

  • Redirection endpoint — used by the authorization server to return responses containing authorization grants to the client via the resource owner user-agent.

OAuth 2.0 Grant Types

OAuth 2.0 grant types define different flows how applications get access tokens from the authorization server. OAuth 2.0 core specification defines four main grant types.

  • Authorization code
  • Implicit
  • Password
  • Client credentials

These grant types are optimized based on different applications and their use cases. Further, there are several extended grant types for additional use cases.

Authorization Code

The authorization code grant type is the most commonly used and secure way of delegating authorization grant. This is a redirection based grant type hence client application should be able to interact with web browsers (user-agent). Different client authentication mechanisms and flow extensions like PKCE, used with the authorization code grant to enhance the security.

Figure 1

  1. The client application initiates the flow and redirects the browser to the authorization endpoint in the authorization server.
  2. The authorization server authenticates the resource owner (via browser).
  3. The authorization server redirects the user back to the client application with an authorization code (code).
  4. The client application authenticates with the authorization server and requests an access token from the authorization server’s token endpoint by including the authorization code.
  5. The authorization server validates the client credential, authorization code, and redirection URI. If valid responds back with an access token and refresh token.
  6. The client application invokes the protected resources in the resource server with the access token.

Authorization Request

https://is.wso2.com/authorize?
response_type=code
&client_id=NHFJ8iff45P7Z0KXhBtVLv9NLsEa
&scope=email profile view
&state=xy25q6ghkz
&redirect_uri=https://playground.com/callback
  • response_type=code: Required, which is used to differentiate the grant type and indicate the credential type that authorization server returns.
  • client_id: Required, application’s client ID. When the application is registered in the authorization it will issue the client ID.
  • scope: Optional, space-separated strings which represent the level of access that the application requesting.
  • state: Recommended, An opaque value used by the client to maintain state between the request and callback. This can be used to prevent security attacks.
  • redirect_uri: Optional, The URL to which authorization server will redirect the browser after authorization granted.

Authorization Response

HTTP/1.1 302 Found
Location: https://playground.com/callback?code=SplxlOBeZQQYbYS6WxSbIA
&state=xy25q6ghkz
  • code: Short living token which represents the authorization grant. Available in the URL parameters. The client must not use this more than once.
  • state: Exact value received from the client in the authorization request.

Access Token Request

POST /token HTTP/1.1
 Host: is.wso2.com
 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
 Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fplayground.com%2Fcallback
  • grant_type=authorization_code: Required, This value must be authorization_code.
  • client_id: Application’s client ID. Required, if the client is not authenticating with the authorization
  • code: Required, The Authorization Code received from the authorization server.
  • redirect_uri: Required, If this was available in the authorization code request values must be identical.

Access Token Response

In a successful authorization grant response contains both access token and refresh token. The entire response looks something like this:

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”
}

Implicit

The implicit grant type was initially designed for the applications such as SPA (Single page application where source code resides in the browser) or mobile applications which can’t securely store the client secret within the applications or if its unable to do a cross origin requests. Compared to authorization code flow access token will be shared as a URL fragment in the initial authorization request eliminating intermediate step of exchanging code with a token. Further it wont issues a refresh token if required to extend the validity of the access token client has to use different methods such as silent refresh.

With modern browser technologies and security threats this grant type is no longer recommended and authorization code is used with modifications over implicit grant type.

Figure 2

  1. The client application initiates the flow and redirect the browser to the authorization endpoint in the authorization server.
  2. The authorization server authenticates the resource owner (via browser).
  3. Authorization server redirect user back to the client application with the access token in the URI fragment.
  4. Client application invoke the protected resources in Resource server with the access token.

Authorization Request

GET https://is.wso2.com/authorize?
response_type=token
&client_id=s6BhdRkqt3
&state=xyz
&redirect_uri=redirect_uri=https%3A%2F%2Fplayground.com%2Fcallback HTTP/1.1
  • response_type=token: Required, which is used to differentiate the grant type and indicate the credential type that authorization server returns.
  • client_id: Required, Application’s Client ID. When the application is registered in the authorization it will issue the client ID.
  • scope: Optional, Space separated strings which represents the level of access that the application requesting.
  • state: Recommended, An opaque value used by the client to maintain state between the request and callback. This can be used to prevent security attacks.
  • redirect_uri: Optional, The URL to which authorization server will redirect the browser after authorization granted.

Access Token Response

In a successful authorization grant response contains the access token in the URI fragment The entire response looks something like this:

HTTP/1.1 302 Found
Location: https://playground.com/callback#access_token=2YotnFZFEjr1zCsicMWpAA
&state=xyz
&token_type=bearer
&expires_in=3600

Password

In the resource owner password credentials grant type, client application directly get the end users credentials (username and password) to the client applications, then pass these credentials to the authorization server in request of access token.

In this flow its not possible to enforce any other authentication mechanisms such as multi factor authentication (MFA) to verify the actual user, and application can get the full access privileges since application has user’s credentials. Hence this grant type is discouraging to use and it should only be used if and only if other flows are not viable. Also, it should only be used if the application is trusted by the end user.

Figure 3

  1. Resource owner provides the client with its username and password.
  2. The client requests an access token from the authorization server’s token endpoint by including the credentials received from the resource owner.
  3. The uthorization server authenticates the client and resource owner and issues an access token and refresh token.
  4. The client application invokes the protected resources in Resource server with the access token.

Access Token Request

POST /token HTTP/1.1
 Host: is.wso2.com
 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
 Content-Type: application/x-www-form-urlencoded
 grant_type=password
 &username=ishara
 &password=A3ddj3w
  • grant_type=password: Required, which is used to differentiate the grant type.
  • client_id: Required, application’s client ID. When the application is registered in the authorization it will issue the client ID.
  • username: Required, resource owner user name.
  • password: Required, resource owner password.
  • scope: Optional, Space separated strings which represents the level of access that the application requesting.
  • state: Recommended, An opaque value used by the client to maintain state between the request and callback. This can be used to prevent security attacks.

Access Token Response

In a successful authorization grant response contains both access token and a refresh token. The entire response looks something like this:

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”
 }

Client Credentials

In the case of end user (resource owner) and client application are same, client credentials grant type is used. Since application is the resource owner, no end user authorization required, only client credentials are used to authenticate with the authorization server. In the machine to machine communications this grant type is mostly used.

Figure 4

  1. The client authenticates with the authorization server and requests an access token from the token endpoint.
  2. The authorization server authenticates the client, and issues an access token.
  3. Client application invoke the protected resources in Resource server with the access token.

Access Token Request

POST /token HTTP/1.1
 Host: is.wso2.com
 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
 Content-Type: application/x-www-form-urlencoded
 grant_type=client_credentials

The authorization server MUST authenticate the client.

  • grant_type=client_credentials: Required, which is used to differentiate the grant type.
  • client_id: Required, application’s client ID. When the application is registered in the authorization it will issue the client ID.
  • scope: Optional, Space separated strings which represents the level of access that the application requesting.
  • state: Recommended, An opaque value used by the client to maintain state between the request and callback. This can be used to prevent security attacks.

Access Token Response

In a successful authorization grant response contains the access token. The entire response looks something like this:

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 Flow

With the authorization code grant type or client credentials grant type refresh token is issued. If the access token is expired, or to get a new access token with reduced scope refresh token grant can be used. In this flow without end users interaction, authorization server will validate the refresh token and issue a new access token.

Figure 5

  1. The client authenticates with the authorization server and requests an access token from the token endpoint.
  2. The authorization server authenticates the client, and issues an access token.
  3. Client application invoke the protected resources in Resource server with the access token.

Request

POST /token HTTP/1.1
 Host: is.wso2.com
 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
 Content-Type: application/x-www-form-urlencoded
 grant_type=refresh_token
&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
  • grant_type=refresh_token: Required, which is used to differentiate the grant type.
  • Required, refresh token received from the authorization server.
  • Optional, originally access granted scopes or limited access compared to originally granted scope.
  • Recommended, an opaque value used by the client to maintain state between the request and callback. This can be used to prevent security attacks.

Response

In a successful authorization grant response contains both access token and a refresh token. The entire response looks something like this:

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”
 }

Which OAuth 2.0 Grant to Use

Grant types define different flows that can be used to get an access token in different use cases. There are pros and cones in each grant type so based on our need we need to evaluate the trade-offs and select the best grant type. In the future I’ll discuss how these grant types best fit with different application types and use cases in advance. Until that here I have listed the general recommendation of using grant types.

  • Resource owner and client application are same / Machine to machine communication
  • Client credentials grant type is recommended in this use case. No end user interaction hence client credentials are used to authenticate client into the authorization server when requesting access token.
  • Web / SPA (single page application) / Mobile applications
  • Authorization code grant type is the recommended grant type for all of these applications. There are different extensions like PKCE and application specific recommendations on using authorization code flow in each of these applications types. If there are no limitations application developers should retain from using implicit and password grant types for these use-cases. In future I’ll will discuss separately on each application type.
  • Other Use-cases: Based on different use cases OAuth 2.0 framework had been extended and implement different grant types such as, SAML 2.0 bearer grant type, JWT bearer grant types etc. Hence based on use cases, evaluating security considerations developers should use each of these extensions.

Next Step

The OAuth 2.0 Authorization Framework specification only discuss the core of OAuth 2.0 framework, yet there are many aspects undefined. Over time these missing pieces were added as additional specs and new improvements still being added as draft specifications. It’s essential to learn each of these specifications to understand the full OAuth 2.0 framework, but scattered nature of these specifications is challenging. In OAuth 2.0 Building Blocks, article, I’ll list down different OAuth 2.0 specifications and their relations.

Resources

RFC 6749 — The OAuth 2.0 Authorization Framework : https://tools.ietf.org/html/rfc6749

Undefined