Demystifying OAuth Flows

Authentication

As you already must be knowing, OAuth 2.0 is an industry-standard authorization protocol. OAuth flows are essentially processes supported by OAuth for authorization and resource owners for authentication. There are OAuth flows enabling users to enter credentials via an OAuth login prompt directly into the app, or even supporting authentication without user involvement for back-end systems. Let’s learn more.

OAuth flows are processes that can vary. There are OAuth flows that allow users to enter credentials via an OAuth login prompt, directly into the app. Some even support authentication without user involvement for back-end systems. Before we learn about the main kinds of OAuth Flows, let’s cover the basics.

The OAuth protocol uses the following roles:

  • Resource Owner — This is basically an entity that grants access to protected resources. More often than not, this is a user.
  • Resource Server — This is the server that holds the resources the Resource Owner needs access to. The Resource Server exposes an API, and the objective of OAuth is to grant secure access to this API.
  • Client — This is an application that requests access to protected resources, typically for a Resource Owner using the application.
  • Authorization Server — This is a server responsible for accepting credentials from the Resource Owner, checking if they are authorized to access a restricted resource, and providing an access token to allow access.

Related: OAuth Grant Types

OAuth Flow Types

Without further ado, let’s dive into the OAuth Flow types you need to know before getting started and working on your specific use case/s.

1. Authorization Code Flow

Authorization Code Flow exchanges an authorization code for a token. For this exchange to take place, you have to also pass along your app’s Client Secret. The secret must be securely stored on the client side.

Use Cases: Server side web applications where the source code is not exposed publicly.

How this OAuth flow works:

  1. The user clicks on a login link in the web application.
  2. The user is redirected to an OAuth authorization server, after which an OAuth login prompt is issued.
  3. The user provides credentials according to the enabled login options.
  4. Typically, the user is shown a list of permissions that will be granted to the web application by logging in and granting consent.
  5. The user is redirected to the application, with the authorization server providing a one-time authorization code.
  6. The app receives the user’s authorization code and forwards it along with the Client ID and Client Secret, to the OAuth authorization server.
  7. The authorization server generates an ID Token, Access Token, and an optional Refresh Token, before providing them them to the app.
  8. The web application can then use the Access Token to gain access to the target API with the user’s credentials.

2. Client Credentials Flow

The Client Credentials Flow allows applications to pass their Client Secret and Client ID to an authorization server, which authenticates the user, and returns a token. This happens without any user intervention.

Relevant for: M2M apps (daemons, back-end services, and CLIs). In these types of apps, the system authenticates and grants permission behind the scenes without involving the user, because the “user” is often a machine or service role. It doesn’t make sense to show a login prompt or use social logins.

How this OAuth flow works:

  1. The application authenticates with the OAuth authorization server, passing the Client Secret and Client ID.
  2. The authorization server checks the Client Secret and Client ID and returns an Access Token to the application.
  3. The Access Token allows the application to access the target API with the required user account.

3. Resource Owner Password Flow

The Resource Owner Password Flow asks users to submit their credentials via a form. Credentials are transferred to the backend and may be retained for future use, before an Access Token is granted. It’s essential that the app is completely trusted. Therefore, this flow is generally not recommended.

Use Cases: Highly-trusted applications, where other flows based on redirects cannot be used.

How this OAuth flow works:

  1. The user clicks a login link in the application and enters credentials into a form managed by the app.
  2. The application stores the credentials, and passes them to the OAuth authorization server.
  3. The authorization server validates credentials and returns the Access Token (and an optional Refresh Token).
  4. The app can now access the target API with the user’s credentials.
Resource Owner Password Flow
Resource Owner Password Flow

The following flows are less commonly used, so we’ll only cover them briefly.

4. Implicit Flow with Form Post

This flow uses OIDC to implement a web sign-in that functions like WS-Federation and SAML. The web app requests and receives tokens via the front channel, without requiring extra backend calls or secrets. With this process, you don’t have to use, maintain, obtain or safeguard secrets in your app. 

Use Cases: Apps that don’t want to maintain secrets locally.

Related: OAuth2 vs SAML

5. Hybrid Flow

This flow can benefit apps that can securely retain Client Secrets. It lets your app obtain immediate access to an ID token, while enabling ongoing retrieval of additional access and refresh tokens. This is useful for apps that need to immediately gain access to data about the user, but must perform some processing prior to gaining access to protected resources for a long time.

Use Cases: Apps that need immediate access to data about the user, but also need to use this data on an ongoing basis.

6. Device Authorization Flow

This flow makes it possible to authenticate users without asking for their credentials. This provides a better user experience for mobile devices, where it may be more difficult to type credentials. Applications on these devices can transfer their Client ID to the Device Authorization Flow to start the authorization process and obtain a token.

Use Cases: Apps running on input-constrained devices that are online, enabling seamless authentication via credentials stored on the device.

7. Authorization Code Flow with PKCE

This flow uses a proof key for code exchange (PKCE). A secret known as a Code Verifier is provided by the calling application, which may be verified by the authorization server using a Proof Key. 

Use Cases: Apps that need to serve unknown public clients who may introduce additional security issues that are not addressed by the Auth Code Flow. 

Which OAuth Flow Is the Right One?

The OAuth 2.0 Authorization Framework powers various authorization flows and grants. Flows are means of obtaining Access Tokens. Selecting the right flow for your use case depends on your app type, but you should also consider other parameters like the client’s level of trust and the user experience.

When choosing an OAuth Flow, take into account the following:

  • Resource owner— This is an entity that may grant access to resources that are protected. Generally, this is an end-user.
  • Client— This is an application asking for access to restricted resources in the name of the Resource Owner.
  • Resource server— This is a server hosting the safeguarded resources. This is the API you need to access.
  • Authorization server— This is the server that authenticates the Resource Owner and provides Access Tokens once it’s authorized.
  • User agent— This entity enables interaction between a Resource Owner and Client (for instance, a native or a browser application).

Is the Client the Resource Owner?

The type of authorization flow is determined by the type of client, and whether it is a human or machine. In purely machine authorization, the Client is the same as the Resource Owner, so the end-user doesn’t need to provide any additional authorization. In this case, use Client Credentials Flow.

Is the Client a Web App Executing on the Server?

When the Client is a typical web app executive via a server, you should apply the Authorization Code Flow. It provides an Access Token (and an optional Refresh Token) directly to the Client. This is a safer approach than having the Access Token pass through the user’s web browser, which may lead to exposure. 

Is the Client Completely Trusted with User Credentials?

If the Client is trusted, the system may generate a Resource Owner Password Credential Grant. In this scenario, the end-user must provide credentials (passwords and usernames), generally via a digital form. The data is then passed on to the backend. It is essential that the Client is completely trusted. 

This grant must only be employed when a redirect-based flow (Auth Code Flow) is not viable. For such cases, use the Resource Owner Password Flow.

Is the Client a Single-Page Application?

A Single-Page Application (SPA) is a browser-based one that employs scripting languages like JavaScript. When the Client is a Single-Page Application, you can use one of two grant options—the Implicit Flow with Form Post and the Authorization Code Flow with PKCE. 

The preferred option is usually the Authorization Code Flow with PKCE as the client-side Access Token. It is not exposed and can deliver Refresh Tokens.  

Is the Client a Native Mobile Application?

When using native applications, you should probably opt for the PKCE (Proof Code for Code Exchange) Authorization Code Flow. Learn more here.

Summing it Up

As you must have already realized by now, the OAuth Flow needs to be picked wisely to optimize your use case and address specific challenges. For example, you may have a single app that requires access tokens for various resource servers. Multiple calls to /authorize will be needed. Learn more here. Making the wrong choice can have serious security and compliance implications today. 

Before getting started, you may also want to check out RFC 6749 and RFC 7636 to better understand the steps involved in implementing these flows.

Subscribe
Notify of
guest
Conversations(0)
Inline Feedbacks
View all comments