The Right Flow for the Job: Which OAuth 2.0 Flow Should I Use?
Get help choosing the right OAuth 2.0 flow for the job.
Join the DZone community and get the full member experience.Join For Free
What Is What in OAuth 2.0
OAuth 2.0 is a well-adopted delegated authorization framework that is already with us for many years and seems to be 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.
- 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 the requested scopes as well.
- In the response, the Authorization Server sends an Access Token.
- 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 Authorization Code Grant is 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.
- 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.
- Resource Owner authorizes the Client by granting permissions requested by the Client.
- Authorization Server redirects the User Agent back to the Client (using redirect URI from point 1). The redirect URI includes a temporary Authorization Code (as a query param).
- Client requests an Access Token from the Authorization Server. The request includes Client ID, Client Secret, and Authorization Code received in the previous step.
- If everything is valid, the Authorization Server returns Access Token and, optionally, a Refresh Token.
- 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 the Authorization Code forwarded through the User Agent. What’s the problem with going through the browser? OAuth 2.0 doesn’t require Client-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 Plain Text. If someone intercepts it, it’s still useless without the 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 recent years, the variations of this flow have been used also for single-page and mobile applications.
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 step four of the previous diagram, an Authorization Code is exchanged for an Access Token without sending the 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.
- Client mobile app opens a browser with the authorization request. Authorization request consists of Client ID, requested scopes, redirect URI, and Code Challenge.
- An authorization request is sent to Authentication Server
- Resource Owner authorizes Client.
- As a result, the Authorization Code is returned to the User Agent.
- Authorization Code is passed to the Client.
- Client app sends the Authorization Code and Code Verifier together with redirect URI and the Client ID to the Authorization Server.
- 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)
- The 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.
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 the browser and might not be implemented securely in other environments. However, as mentioned previously, for SPA, in 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. The 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.
- Resource Owner submits his credentials to the Client application.
- Client forwards the credentials to the Authorization Server.
- Authorization Server returns Access Token (and optionally a Refresh Token)
- 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.
It’s a new extension flow added to OAuth 2.0 to cover the scenario when a device has an Internet connection but doesn'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.
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 at DZone with permission of Grzegorz Mirek, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.