OAuth 2.0 vs OAuth 2.1

Dhaura Pathirana
6 min readJul 18, 2022

OAuth stands for Open Authorization and is a lightweight protocol for secure access delegation. It is a token-based access delegation method where a third-party application does not need the username and password of a user to access the user’s resources. Even though OAuth 2.0 is the most widely used version of OAuth, OAuth 2.1 is an ongoing solution that accommodates and simplifies many extensively used features of OAuth 2.0.

Please refer to the following blog for more information on OAuth2.0 and its grant types.

OAuth 2.0 was originally published in 2012 but since then, the core specification has been extended and expanded and, several other specifications were built on top of that. This makes it really difficult to keep track of all the new best practices and changes of OAuth. Hence, OAuth 2.1 has been introduced and it captures all the best practices of OAuth 2.0 while introducing its well-formed extensions under a sole name.

Now, let’s move on to the main differences between OAuth 2.0 and 2.1.

1. Authorization Code flow must be accompanied by PKCE

Authorization code is one of the most secure grant types that was introduced by the OAuth 2.0 specification. Using this flow, a user can delegate his/ her access to a certain application easily and securely. But there were a few security issues regarding this access delegation flow such as CSRF and authorization code injection attacks where the attacker can intercept and modify the content of the request (especially with non-TLS connections).

In order to overcome this issue, PKCE (Proof Key for Code Exchange) was introduced and it has a mandatory requirement where an extra one-time code must be sent to the authorization server in order to obtain the token. As this code validates the request, it can be found whether the request was modified by an attacker.

The following diagram illustrates how authorization code flow works with PKCE enabled.

Authorization Code Grant with PKCE

With the initial request, the client will send a PKCE challenge code and its method to the authorization server. After receiving the authorization code, the client will send the authorization code with the PKCE challenge code verifier to the authorization server. The access token is issued only if the challenge code verifier matches the received challenge code and its method.

Hence, with OAuth 2.1, it is mandatory for Authorization code grant to use PKCE challenge to verify the request.

2. Implicit and Password Grants are omitted.

Implicit grant was one of the simplest grant types in OAuth 2.0. But with its simplicity, it became more vulnerable. This is a simplified version of the Authorization code where the access token is directly given to the client by the authorization server without the authorization code. Thus, making the process inherently insecure and the access token vulnerable to attackers.

Implicit Grant

Especially, when SPAs are considered the access tokens can be easily stolen since the token will be passed in the URL fragment or will be stored in the local storage.

When the Password grant is considered, the resource owner will give his/ her own credentials to the client, and the client will exchange them with the authorization server for an access token.

Password Grant

This is quite contradictory since it does not eliminate the issue that the OAuth access delegation is based on and that is to give a third-party application limited access to a user’s resources without giving the username and the password of the user to the client. Hence, it shatters the core access delegation pattern of OAuth.

As the client receives the username and password of the user, the client is permitted to use it for any purpose. Thus, the resources of the owner will be vulnerable, and especially, if the client is not trusted, the user will have to face a lot of repercussions.

Due to these security vulnerabilities, these grant types are omitted from the OAuth 2.1 specification. If your application already uses one of these two grant types, the best option is to switch to Authorization Code grant.

3. Redirect URIs must be compared using exact string matching

In OAuth, a redirect URI is configured in order to figure out where the client should be sent after issuing the access token. A typical redirect URI will look like the following.

http://localhost:8080/callback

But there will be cases where you want to configure multiple URIs and use the correct one according to the situation. In that case, one of the major solutions with the OAuth 2.0 specification was to use a wildcard URI such as the following.

http://localhost:*/callback

Therefore, any URI that matches the pattern will be considered a valid redirect URI. Thus, making it a security risk, and an attacker can easily change the redirect URI (due to flexible URI matching) and redirect the user to one of the attacker’s servers. Hence, with OAuth 2.1, even though it compromises some flexibility, it is mandatory to compare the redirect URI using exact string matching. That means the redirect URI should look like the first example.

4. Passing Bearer Tokens in the query string of URI is omitted.

A bearer token is the token that is given to the client to access some resources on behalf of a user. Therefore, the client will send this bearer token to the application server with the necessary API call. With OAuth 2.0 specification, bearer tokens were allowed to be passed in the following ways.

  1. HTTP request header
  2. POST body of the request
  3. A query string in the URL

In general, sending in any parameter in the URL is not private and thus, it makes the parameter vulnerable. These parameters can be stored in caches, histories and logs, and they can be easily snatched by any JavaScript running on the page. Therefore, sending a bearer token as a query string parameter in the URL is highly insecure. Hence, the above practice is omitted from the OAuth 2.1 specification.

5. More secure Refresh Tokens

Earlier, under OAuth 2.0 specification, refresh tokens were introduced to create new access tokens without re-authentication when the current access token expires. Threfore, usually, the expiry time of a refresh token is much longer than that of an access token. Hence, if a refresh token gets stolen by an attacker, the attacker can generate access tokens at his will. Then the resources that access tokens were issued for will not be secure anymore.

In order to secure refresh tokens, OAuth 2.1 specifies two methods a refresh token can be issued.

  1. One-time only refresh token— a refresh token can be used to create only a single access token. After this access token creation, the refresh token will be invalid. The authorization server will send another refresh token with the new access token, for future use.
  2. Sender constrained refresh token — a refresh token will be bound to the client cryptographically. Therefore, when an access token request is made with a certain refresh token, the authorization server will have a way to verify whether the requester is the intended client.

In conclusion, OAuth 2.1 requires the OAuth server to protect refresh tokens more securely.

Apart from the above major differences, OAuth 2.1 inherits all the other characteristics and behavior from OAuth 2.0 specification (except for some other few properties that were explicitly removed or replaced). On another note, an effort for OAuth 3 is already underway and it’s said that OAuth 3 is going to be a whole new approach for OAuth.

--

--