Understanding OAuth2 Landscape

(Source — https://www.economist.com/gulliver/2018/05/08/two-hackers-have-found-how-to-break-into-hotel-room-locks)

Now it has been nearly 8 years after the formal approval of OAuth2 Core standard by IETF. Obviously, the OAuth2 is not a new technology for writing yet another introduction post, especially in 2020. So what has motivated me to write an introductory post about OAuth2 at this point? I believe it’s worth discussing that first.

  1. Security technology is evolving relatively fast compared to other technology, this is true for the OAuth2 as well. Some of the content of the spec is no longer considered as best practice and discouraged to use as well. This has happened because some of the technological constraints existed in back then are no longer valid now. This is also due to the fact that the discovery of new vulnerabilities that affect some parts of the spec. So it’s worth to refine the way we use Oauth2 according to the current best practice.
  2. In the OAuth2 core spec, a relatively large number of elements that are required for practical implementations were intentionally left undefined. During the recent past, OAuth2 has evolved from a core spec to an eco-system with a number of supportive specs, and some of which are still under the development too. Therefore after 8 years, we are in a much better position to present a more complete and comprehensive picture about how to implement OAuth2 in terms of open standards.
  3. As we will discuss a little later with further details, the semantics of requesting an authorization token from an authorization server by a client is defined as ‘grant type’. There are a number of grant types that have been developed after the core spec; so again, it’s worth discussing them and provides a consolidated view on when and how to use them.
  4. As anticipated by the original authors, the OAuth2 core spec is being used as a foundation to derive some other technology: OpenID Connect (OIDC) authentication protocol and User-Manager Access (UMA2) access management protocol all are good examples. Thus it’s important to understand how these new technologies have been developed on top of OAuth2.

Access Delegation

The OAuth2 introduces itself as an authorisation framework. Although there is no issue with the term, I would much prefer to call the OAuth2 an ‘access delegation’ framework. However, it seems there is considerable confusion about OAuth2 as an authentication technology; nevertheless, it’s a topic for another post.

Before the OAuth2 era, when you created a Twitter account and Twitter wanted to send friend requests to your contact list stored in Gmail, it used to ask for your Gmail username and password promising you that they would “behave appropriately” with those credentials and wouldn’t misuse them.

(Source — https://www.slideshare.net/prabathsiriwardena/oauth-20-with-pet-care-house )

As you can easily understand, this is not acceptable in terms of security, and this problem has opened up the potential to invent a new technology that we call OAuth2 today. The Oauth2 facilitates to implement the above-discussed use case without sharing original credentials, instead of using a temporary token with a great level of control.

Pre-Oauth era Vs OAuth2 era

To give you a real-world example; this is bit smiler to the use of an access card system in a hotel rather than physical keys. The access card provides numerous benefits over traditional keys, some of them are listed below.

  • The access card itself doesn’t contain any useful information instead it’s just a reference issued by the security system and used by the security system to execute a set of pre-agreed actions; in this case, to open the door of a particular room only during a certain time period. However, once the card is presented to the security system, the system can easily identify details such as to whom the access card was issued, issued time and the authorized person who issued the card, validity period of the card, what rooms are allowed to be accessed etc.
  • In a scenario where multiple access cards being used to access a particular room, the security system can track some audit logs such as who has accessed the room during a particular time.
  • Unlike physical keys, if a stolen, access card possesses very low-security risk because security system can revoke a stolen access card with a single click.
  • There is no requirement to collect the access card during the check-out time and there is no great risk of creating duplicate cards because if someone managed to create identical duplicate access card, it could be only used for a limited period.
  • It’s easy to rotate the new card and easy to revoke access cards from a security systems level.
  • If you present your access card to the door of another room, it wouldn’t work. In other words, this card knows its audience.
  • However, the access card can’t verify whether the room is accessed by the original person who was issued an access card, it could be someone else who carries the access card.

At this point, I want you to think the above hotel access card is identical to the temporary token used in OAuth2; and all of the above points are also applicable to OAuth2 token as well. I hope your next hotel visit will remind you about OAuth2.

OAuth2

In the standard OAuth2 flow it constitutes 4 basic roles or actors know as the resource owner, the resource server, the authorisation server and the client. The following diagrams help you to understand the above roles/actors based on the real-world examples that have mentioned in the previous sections.

OAuth2 roles based on hotel example

OAuth2 roles based on Twitter example.

The Resource Owner (RO): The owner of the underline resource that the client wants to access. For example, this could be your photos stored in Flickr, a file stored in DropBox, Gmail contact list or your Facebook profile etc.

The Client: This is the 3rd party application that wants to access the service. For instance, a photo printing application may want to access your photos hosted in Flickr. In that case, the photo printing application acts as the OAuth2 client.

The Resource Server (RS): This is where the resource owners store their resources. For example Flickr, DropBox and Gmail services.

Authorization Server (AS): This is the entity responsible for coordinating with the client and the resource owner, also provides temporary access tokens to the client. In most of the real-world cases, it’s hard to distinguish this entity from the resource server.

As you have some level of understanding about the above actors, now let’s look at interactions among these actors. First, we will look at abstract OAuth2 flow, the abstract flow means you can’t find this flow in real-world instead this helps you to understand concrete OAuth flows easily like OSI abstract model in computer networking. The abstract OAuth2 flow consists of 3 mains steps as follows.

Step-1 — The client should possess a special token known as an authorization grant, which is a credential representing the resource owner’s (RO) authorization for this particular client. In case the client does not possess a valid authorization grant, it should first request it from the AS. Usually, this happens by redirecting the resource owner (in fact resource owner’s user-agent) to the authorisation server (AS) so that the RO can authenticate with the AS and authorize the client. It’s also important to note that the authorization grant that we are discussing here is again an abstract notion, grant type: another OAuth2 construct which we will look at little later defines the actual format and processing logic for authorization grant.

Step-2 — The client authenticates with the AS and requests an access token by providing the above-discussed authorization grant. The AS validates both the client and the received authorization grant then issues an access token to the client.

Step-3 — The client access the resource on the Resource Server (RO) by producing the access token, this access token can be used multiple times as far is it remains valid. However, the RS should validate the received access token before it returns the requested resource.

Now, it is the best time to introduce the concept of ‘grant type’, the underline mechanism that the client requests an access token is known as grant type, grant types are generally defined based on use cases.

If you look at OAuth2 core spec there are 4 grant types; however; in a contemporary view, 2 grants types should not be used, so it’s more accurate to mention here that there are 2 grants types in the core spec.

  1. Authorisation code grant type
  2. I̶m̶p̶l̶i̶c̶i̶t̶ ̶g̶r̶a̶n̶t̶ ̶t̶y̶p̶e̶
  3. R̶e̶s̶o̶u̶r̶c̶e̶ ̶o̶w̶n̶e̶r̶s̶ ̶p̶a̶s̶s̶w̶o̶r̶d̶ ̶g̶r̶a̶n̶t̶ ̶t̶y̶p̶e̶
  4. Client credentials grant type

Back then web browsers could not make cross-domain requests and limited to access the domain where the website is hosted; this was a major limitation for JavaScript-based applications when using OAuth2. As a solution for this limitation, the implicit grant type was introduced. However, the CORS standard that is supported by most of the modern web browsers has successfully addressed this limitation so today’s JavaScript-based application can use Authorisation code grant type without any issue. The main security issues associated with the implicit grant type are: it can’t support client authentication and also tokens are visible to the RO via the web browser. If you want to read more, take a look at the following blog posts.

The State of the Implicit Flow in OAuth2

Why you should stop using the OAuth implicit grant!

The resource owner password grant type was introduced as a transition step from HTTP BasicAuth to OAuth2 framework. After 8 years of successful adoption, we are no longer in the transition phase, so it’s not required to have transition grant types any more. The main security drawbacks of the resource owner password grant type are: it forces the client to capture username/password from the RO instead of redirecting to the AS, also the RO is limited to use username/password-based authentication. If you want to read more, take a look at the following blog posts.

Why the Resource Owner Password Credentials Grant Type is not Authentication nor Suitable for Modern Applications

In OAuth2 jargon, the term endpoint is used to refer to a network address. There are two main endpoints are available within the AS: authorization endpoint and token endpoint. The authorization endpoint is used to get an authorization grant by the client and the token endpoint is used to request an access token.

The endpoint known as redirection endpoint should be implemented and should be available in the client, this endpoint is used to send authorisation grant and access token by the AS.

OAuth2 Clients

OAuth2 clients are identified using an identifier known as client_id which is unique within the specific AS. Generally, client_id is generated by the AS when a client is registered. In addition to that, some of the ASs support the client to provide its own client_id during the client registration process. Although client_id is used to uniquely identify the application, it does not necessarily identify each and every instance of the client application. As an example, all the instances of a mobile application that have been installed in a large number of mobile devices can use the same client_id.

OAuth2 clients

In addition to that, depending on the client type, each application is provided with a secret called client-secret which can be used to authenticate the client with the AS during the access token request process.

OAuth2 clients are grouped into two wider categories known as confidential clients and public clients, let’s look at each of them with some details.

Confidential clients — These are the clients that can keep the client-secret securely. For instance, a server-side web application hosted in web server can. be considered as a confidential client because it can store a client-secret securely. During the client registration, these clients are provided with a client-secret and suppose to use it for client authentication.

Public clients — These are the type of client that can not keep a client-secret securely. Public clients are very common nowadays, mobile applications, SPA applications such as ReactJS, AngulerJS or clients run on devices are good examples for public clients. Since public clients can’t process a client-secret securely, a client-secret should not be provided to them and the AS should not try to authenticate the public client. Instead of client authentication, the AS must use another OAuth2 extension called Proof Key for Code Exchange (PKCE) with public clients.

By the way, web browser-based clients and device clients such as mobile applications face their own challenges and security concerns; these challenges and constraints are also addressed by the OAuth2 community.

Browser-based application developmentOAuth 2.0 for Browser-Based Apps draft address challenges specific to browser-based application development and define the best practice as well. Some of the challenges include how to use Authorization grant with proper security measures, how to keep access token securely and clarification on various patterns related to browser-based applications.

Device-based application developmentOAuth 2.0 for Native Apps is a current best practice document that addresses the challenges and security issues related to device-based clients such as rich mobile applications. Some best practice includes how to redirect the end-user to the AS server via system browser instead of framework level mechanisms, callback URL techniques and best practices related to security issues.

Authorization code grant type

Authorisation code grant type is the widely used grant type and the recommended grant type for the most of the use cases including server-side web applications, browser-based client-side applications and mobile applications that based on iOS and Android.

As you can see in the following diagram, the flow of the Authorisation code grant type is pretty much identical to the abstract OAuth2 flow that we have discussed earlier. Let’s examine the authorisation code grant type with some example messages.

Step -1 — The client makes a HTTP GET call to the Authorisation EP over a HTTPS connection with following parameters, also note that the URL should in application/x-www-form-urlencoded format.

  1. client_id — pre-agreed string identifier which the AS used to uniquely identify this client.
  2. redirect_uri — The address of the redirect endpoint of the client in which the client has registered prior to this call.
  3. scope — This is used to mention requested scopes for the access token.
  4. response_type=code — This is a fixed value for this grant type, the AS use this parameter to determine the grant type.
https://localhost:9443/oauth2/authorize?client_id=g6_E15YBhaMoHeGOzlFR6TpD4_Ua&scope=read&redirect_uri=http://127.0.0.1:5000/&response_type=code

Once the server receives this request, it validates client_id and redirect_uri, if there is no issue found it will redirect the user-agent to the authentication page of the AS in order to authenticate the resource owner. Usually, this will be followed by a number of redirect calls based on authentication configuration of the server; in terms of OAuth2, it doesn’t matter how does the AS authenticate the RO.

Once the authentication and authorization are successful, the server returns a valid authorization grant in which represent the approval of the RO the client. The AS uses user-agent to send the authorization grant to the redirect-EP of the client, usually by executing an automatic HTML form submission via a script. This also means that authentication grant ( code) is visible to the RO via the user-agent.

http://127.0.0.1:5000/?code=9bf93eb9-d1de-3fc2-950c-4f17d79d8876

Step -2 — During this step, the client directly call the token endpoint of the AS without using the web browser; typically making a POST request over HTTPS. The following are the most important parameters of this request.

  1. grant_type=authorization_code — this is a constant parameter value used to differentiate authorisation grant type based token requests from other token requests.
  2. redirect_uri — The address of the redirect endpoint of the client in which the client has registered prior to this call.
  3. code — This is the value that the client has received in the previous step.

Also, note that the client_id and the client_secret should be sent using HTTP HTTP Authorization header in order for the AS to authenticate the client. This value takes base64(client_id:client_secret) format.

curl -k -X POST - user "g6_E15YBhaMoHeGOzlFR6TpD4_Ua:BhUDJqMoYo8mgfU6f3fZXn16BEUa" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=authorization_code&code=1ca46bf5-dffe-38fc-a576-f04f97ce5a28&redirect_uri=http://127.0.0.1:5000/" https://localhost:9443/oauth2/token

Upon receiving the above request, the AS first try to authenticate the client and then verify the received code and redirect_uri values. If everything is ok, the AS returns an access token to the client with additional metadata.

{
"access_token":"48c4abd3–3f7e-3eee-8ac8–9e3fd0c435ec",
"refresh_token":"488c282a-7b11–3b57-b907-ae1cc90680f4",
"scope":"read",
"token_type":"Bearer",
"expires_in":3600
}
  1. access_token — This contains the access token for the client.
  2. refresh_token — This token can be used to request an access token once the current access token expired without going through the step-1, we will discuss this topic separately.
  3. token_type — The type of token.
  4. expires_in — validity period of the current access token.

Step -3 — Client access the protected resource on the RS by presenting the access token. It is expected from the RS to validate the access token by contacting the AS or some other means before it grants access to the resource.

curl http://api.example.com/articles  -H "Authorization: Bearer 48c4abd3–3f7e-3eee-8ac8–9e3fd0c435ec"

Note that, the value of HTTP Authorization header use Bearer ACCESS_TOKEN format.

Client Credentials grant type

Sometimes the above-discussed Authorization Code grant type is known as a 3-legged OAuth2 flow because it involves three parties: the AS, the client and the end-user; in contrast to that Client Credentials grant type is known as a 2-legged OAuth2 flow because it only involves two parties: the AS and the client. As an example, a Facebook client installed on your mobile device accessing the Facebook API to get some application data ( not user data or user-specific data) can be considered as a use case for Client Credentials grant type. Also, note that this grant type is only applicable to confidential clients because client authentication is a requirement of this grant type.

Step -1 — The client makes a HTTP GET call to the Token EP over a HTTPS connection with following parameters, also note that the URL should in application/x-www-form-urlencoded format.

  1. grant_type=client_credentials — this is a constant parameter value used to differentiate client credentials grant type based token requests from other token requests.
  2. scope — This is used to mention requested scopes for the access token.

Also, note that the client_id and the client_secret should be sent using the HTTP Authorization header in order for the AS to authenticate the client. This value takes base64(client_id:client_secret) format.

     POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=client_credential

Upon receiving the above request, the AS first try to authenticate the client. If everything is ok, the AS returns an access token to the client with additional metadata.

{
"access_token":"48c4abd3–3f7e-3eee-8ac8–9e3fd0c435ec",
"refresh_token":"488c282a-7b11–3b57-b907-ae1cc90680f4",
"scope":"read",
"token_type":"Bearer",
"expires_in":3600
}
  1. refresh_token — This token can be used to request an access token once the current access token expired without going through the step-1, we will discuss this topic separately.
  2. token_type — The type of token.
  3. expires_in — validity period of the current access token.

Step -3 — Client access the protected resource on the RS by presenting the access token. It is expected from the RS to validate the access token by contacting the AS or some other means before it grants access to the resource.

curl http://api.example.com/articles -H "Authorization: Bearer 48c4abd3–3f7e-3eee-8ac8–9e3fd0c435ec"

Note that, the value of HTTP Authorization header use Bearer ACCESS_TOKEN format.

Proof Key for Code Exchange (PKCE)

PKCE is the acronym for Proof Key for Code Exchange — which is an extension for OAuth2 framework. As we discussed in a previous section PKCE must be used with public clients when they generating access tokens. However, it’s recommended to use PKCE with confidential clients as well.

In short, a one-time randomly generated cryptographical key is generated by the client and pass to the AS with the initial authorization request and the subsequent token request. The idea here is if an attacker manages to hijack the authorization grant (a.k.a ‘code’), still it can not use it to generate an access token because the PKCE key (known as ‘code verifier’ ) is unknown to the attacker.

Up to now, we have covered basic grant types defined in the core framework. In the following sections, I will introduce other extension grants types widely used today in brief and I hope to cover these grants type in details in my future posts.

Refresh Token grant type

I believe you remember about the refresh token returned along with access token request, the purpose of this refresh token is to allow clients to request new access by presenting a valid refresh token without reauthenticating the end-user again. This usually happens once the current access token expired and greatly enhance the user experience. This flow is much similar to the token request (2nd interaction) of the Authorization Code grant type, but refresh token grant type uses a “Refresh token” instead of an “Authorization code” to request a new access token.

Once the token request received, the AS checks the validity of the refresh token along with some other checks and if everything is ok then return a new access token usually along with another refresh token which can be used subsequently.

Refresh Token grant type

SAML Assertion and JWT Assertion grant types

In Authorization Code grant type, the client does not possess any credential or any authorization token from the end-user, and that is why it has to redirect the end-user to the AS and acquires an “Authorization code” first (which represent the end-user approval ) before requesting an access token.

So, what would be the situation if the client possesses some kind of security tokens such as SAML token or JWT token?

As you can imagine, there are OAuth2 extension grant types that allow the AS to accept these security tokens as valid authorization grants and issue an access token in return.

SAML Assertion grant type facilitates a client to pass a SAML token and requests an access token and JWT Assertion grant type facilitates a client to pass a JWT security token when requesting an access token. Both of these grant types leverage great level of flexibility to OAuth2 framework to interoperate with other security eco-systems, especially with SAML based previous-generation web SSO environments.

SAML Assertion grant type
JWT Assertion grant type

Token Exchange grant type

This grant type facilitates to request a new access token by presenting an existing token mainly to support impersonation and delegation use cases. This grant type needs to be discussed in detail so I will cover it in a future post.

OAuth2 token types

The OAuth2 framework does not specify any specific token format and lets implementers (usually ASs) define the format of the token and attributes of the token. A brief summary of two widely used token types is given below.

Opaque Bearer — As its name implies this is a reference type-token; this means no sensitive user data are encoded in the token. If an attacker manages to receive a token, the attacker can not find any useful information by decoding the token, most of the cases this is just a random string. Generally, the AS that issued the token can provide information about the token to the authorized parties such as AS once the token is presented to the AS; technically, this is known as Token Introspection. As you can expect, there is a separate spec for that as well.

The other main characteristic of the opaque bearer token is whoever processes the token can legitimately use the token without proving their identity. In real-world, this is similar to use of currency notes at a shop where anybody can use them without proving their identity in contrast to credit cards where it’s necessary to have a signature check or a secure pin.

JWT Bearer — Use of this token type is similar to opaque bearer token: that is whoever holds the token can legitimately use it. However, the main difference is sensitive user and token data are encoded within the token. In some environments, this may present a security risk but token encryption can mitigate the potential risk up to an acceptable level. The main advantage of this access token type is intended audience ( such as RS ) can themselves validate and access user and token data without contacting the issued AS.

Token Introspection

In the previous section, we discussed that opaque (bearer) tokens do not contain any useful information about the user or the token itself, and it’s required to contact the issued AS to verify and learn details about the token. The Token Introspection spec standardize this interaction with the client and the AS. By presting a token to the introspection endpoint defined by the specification, an authorized party can receive information about the token such as the validity of the token, expiration of the token and attributes related to the end-user etc.

Token Revocation

By design, access tokens are meant to be expired after a short period without any external intervene; however, there can be situations that the token need to be revoked before its expiration period, especially access token with a long or infinite expiration time. In such cases, the OAuth2 framework defines special endpoint called revocation endpoint that allows authorized parties such as the end-user and the OAuth2 client to revoke the token. Once revoked, the access tokens become invalidated and can’t be used further.

Authorization Server Metadata

At this point, you are aware that, to request an access token from an AS a client should know some information about the AS such as URLs of token and authorization endpoints, supported grant types, supported scopes, the identity of the AS etc. One possible approach to make this information available is to have human-readable documentation somewhere so that the client application developer can access it. This approach is still widely used and quite popular as well.

The other option is, facilitate to discover the above information via an automated mean, and that is the intended purpose of Authorization Server Metadata specification. It defines a standard endpoint and message semantics, by sending a request message an OAuth2 client can receive information about the AS.

Client registration & Client Manamgnet

In a previous section, we discussed that having a client _id and a client_secret as a prerequisite to making a token request; but, we haven’t discussed how a client can register with an AS to receive a client _id and a client_secret. In brief, a client can use the following approaches:

  1. Online portal — application developers can register themselves with the AS and generate a client _id and a client_secret. Most of the social identity providers such as Facebook, Twitter use this approach.
  2. Offline channels — Client developers can contact the support staff of the AS via e-mails or some other means to register the application and receive a pair of a client _id and a client_secret.
  3. Dynamic Client Registration (DCR) — This is a RESTful endpoint exposed by the AS. The client applications can dynamically register with the AS by sending a registration request, and receive client _id and a client_secret as well.
  4. Dynamic Client Registration Management (DCR -M) — This is also a RESTful endpoint exposed by the AS and going had in hand with DCR. DCR standard is limited to client registration only, while DCR -M standard defines semantics to modify and delete client application.

OAuth2 extensions

There are a number of OAuth2 extensions are available, among them, it's worth to discuss the following two. However, these are good candidates for separate posts.

OpenID Connect — This is an identity protocol extended from OAuth2. If you are familiar with SAML, OpenID Connect use cases are almost identical to that.

UMA2 — OAuth2 is mainly about access delegation to an application, mainly to a non-human. As an end-user, how do you delegate access to a human to access your resources on behalf of you? That is the primary problem space of UMA2 standard which is also an OAuth2 extension.

Also, note that as of writing this post there is an on-going effort within the OAuth2 working group to develop OAuth 2.1 specification targeting to cover the wider scope and up to date practice. You can refer to the current draft of 2.1 specs from here.

This is a very long post; but, I believe I have provided you with a comprehensive picture not only about the core OAuth2 specification but also about the supporting standards of the OAuth2 eco-system. You also can find all OAuth2 related specifications and their current status from here. I hope to write similar posts about each of these supporting specifications as well.

Integration and Identity Architect & PMC Member @ The Apache Software Foundation, was a Director @ WSO2