Enterprise Java

The Right Flow For The Job: Which OAuth 2.0 Flow Should I Use?

What is What in OAuth 2.0

OAuth 2.0 is a well-adopted delegated authorization framework which is already with us for many years and seems that it is here to stay. If you are not familiar with the basic concepts of OAuth 2.0, there is an
excellent article written by Takahiko Kawasaki. Here is just a quick reminder of the OAuth 2.0 parties:

  • Resource Owner – an owner of the protected resource, e.g. user
  • Client – an application that  wants to get access to a protected resource, e.g. server-side web app or single-page application (SPA)
  • Authorization Server – a server that issues tokens
  • Resource Server – a server that manages Resource Owner’s protected data

Let’s go through each OAuth 2.0 flow and discuss their usages.

Client Credentials Grant

It’s the simplest flow. It allows a Client to request an Access Token using its Client ID and Client Secret. Both are kept securely on the Client side and registered in an Authorization Server.

OAuth 2.0 Flow
  1. In the first step, the Client sends an HTTP request to the Authorization Server including its Client ID and Client Secret (in Authorization header, for example). The request may include requested scopes as well.
  2. In the response, the Authorization Server sends an Access Token.
  3. The Client uses the Access Token to call Resource Server.

When to use?

As you can see, there is no user involved. Client Credentials Grant is recommended for machine-to-machine authorization. Typically, one trusted service calling another.

Authorization Code Grant

The most commonly used flow, designed especially for server-side applications that can maintain the confidentiality of their Client Secrets. It’s one of the redirection-based flows.

OAuth 2.0 Flow
  1. The Client initiates the flow by redirecting the User Agent of the Resource Owner to the Authorization Server. The Client includes its Client ID, requested scopes and the redirect URI.
  2. Resource Owner authorizes Client, by granting permissions requested by the Client.
  3. Authorization Server redirects User Agent back to the Client (using redirect URI from point 1). The redirect URI includes a temporary Authorization Code (as a query param).
  4. Client requests an Access Token from the Authorization Server. The request includes Client ID, Client Secret, and Authorization Code received in the previous step.
  5. If everything is valid, the Authorization Server returns Access Token and optionally, a Refresh Token.
  6. The client uses the Access Token to call the Resource Server on behalf of the Resource Owner.

Why do we need the additional Authorization Code?

Why can’t we just request an Access Token directly? Why was the Authorization Code introduced in the first place? It turns out that main goal was to separate the information exposed to a Client and User Agent. Notice that Access Token doesn’t go through the browser at all. It’s requested from the Client (server-side app) using

Authorization Code forwarded through the User Agent. What’s the problem with going through the browser? OAuth 2.0 doesn’t requireClient server to support HTTPS. So technically, there might be a redirect to a Client server which isn’t done over SSL. If that happens, Authorization Code is sent via plaintext. If someone intercepts it, it’s still useless without Client Secret. However, if you would  directly send an Access Token via HTTP, it could be compromised.

When to use?

As mentioned earlier, this flow is recommended for server-side web applications. However, in the recent years, the variations of this flow has been used also for single-page and mobile applications.

Single-Page Apps

For single-page applications, the only difference is that Client (SPA) doesn’t have Client Secret. Since the SPA run in a browser, and its source code is sort of public, a Client Secret cannot be kept confidential on a browser side. That’s why in the step 4 of the previous diagram, an Authorization Code is exchanged for an Access Token without sending Client Secret.

Native Mobile Apps

Similarly to SPA, native mobile apps are considered to be public, not confidential clients. That’s the reason Client Secret should not be stored in a mobile device (and thus not sent when requesting Access Token). There might be some security issues with Authorization Code Flow without Client Secret implemented in mobile. One such issue is that the Authorization Code might be intercepted by an attacker and exchanged for an Access Token. To mitigate that risk, there is a technique called Proof Key for Code Exchange (PKCE). For every authorization request, the Client has to create a random key called Code Verifier. Its hashed version called Code Challenge is included into the request for Authorization Code. The Authorization Server should associate this Code Challenge with the Authorization Code that it generates. Later, when exchanging the Authorization Code for an Access Token, Client includes Code Verifier as a query parameter. In addition to validation of the standard parameters, the Authorization Server should also validate the Code Verifier using previously received Code Challenge.

OAuth 2.0 Flow
  1. Client mobile app opens a browser with the authorization request. Authorization request consists of Client ID, requested scopes, redirect URI and Code Challenge.
  2. An authorization request is sent to Authentication Server
  3. Resource Owner authorizes Client.
  4. As a result, the Authorization Code is returned to the User Agent.
  5. Authorization Code is passed to the Client.
  6. Client app sends the Authorization Code and Code Verifier together with redirect URI and the Client ID to the Authorization Server.
  7. The Authorization Server compares a hash of the Code Verifier with the previously sent Code Challenge. If they match, the Authorization Code is exchanged for an Access Token (and optionally Refresh Token)
  8. Client uses Access Token to call Resource Server on behalf of the Resource Owner.

Additionally, the current best practice is to use only external User Agent (not embedded web-views) to send requests for Authorization Code.

Implicit Grant

It’s similar to Authorization Code Grant, but it skips the Authorization Code step completely. The Client requests Access Token directly, without the need for an Authorization Code. Additionally,  Client Secret is not involved. In the Implicit Grant, Refresh Tokens are not used. It’s important to mention that an Access Token is returned in a 3xx redirect with as a hash fragment, which is never sent from the browser.

When to use?

It was initially designed as a flow for SPA. It relies on browser and might not be implemented securely in other environments. However, as mentioned previously, for SPA, in the recent years more and more organizations have been moving towards Authorization Code Flow without Client Secret instead of Implicit Flow .

Resource Owner Password Credentials Grant

In this flow, Resource Owner submits his credentials directly to a Client application. Client application uses that credentials to exchange them directly for an Access Token (and optionally a Refresh Token). Similarly to Client Credentials, it’s a not a redirect-based flow.

OAuth 2.0 Flow
  1. Resource Owner submits his credentials to the Client application.
  2. Client forwards the credentials to the Authorization Server.
  3. Authorization Server returns Access Token (and optionally a Refresh Token)
  4. The Client uses Access Token to call Resource Server on behalf of the Resource Owner.

When to use?

If there is a high degree of trust between the Resource Owner and the Client application. It’s recommended to use it only if other flows are not possible. Most of the original use cases for the Resource Owner Password Credentials Grant can be now covered by Device Flow extension.

Device Flow

It’s a new extension flow added to OAuth 2.0 to cover the scenario when a device has an Internet connection, but don’t have a browser or limited input capability to enter the text, e.g. TV.

In this flow, the device asks the user to open a specific URL on a device with a browser (e.g. smartphone) in order to authorize.

Summary

Here is a quick summary of which flow is designed to be used in a given scenario:

  • server-to-server: Client Credentials Flow
  • server-side app: Authorization Code Flow
  • SPA: Authorization Code Flow without Client Secret or Implicit Flow
  • mobile: Authorization Code Flow with PKCE
  • device without browser: Device Flow

Published on Java Code Geeks with permission by Grzegorz Mirek, partner at our JCG program. See the original article here: The Right Flow For The Job: Which OAuth 2.0 Flow Should I Use?

Opinions expressed by Java Code Geeks contributors are their own.

Grzegorz Mirek

Grzegorz is a software developer from Cracow, Poland. He started his adventure with Java roughly 6 years ago when he was at university and since that time, he keeps expanding his knowledge in this field. He is especially interested in JVM performance and optimisations and this is what he mostly blogs about.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button