Authentication

Demystifying OAuth Flows

OAuth 2.0 is an industry-standard authorization protocol. OAuth flows enable users to authorize access to resources and authenticate resource owners—essentially, they are different ways of retrieving access tokens. The right OAuth flow depends on the application’s needs and requirements.

Here are some examples of OAuth flows:

  • Authorization code flow: This flow allows a client application to access protected resources like web APIs.  It’s designed for confidential applications, such as regular web applications. The app’s client secret must be securely stored on the client side. This flow is suitable for server-side web applications where the source code is not exposed publicly.
  • Client credentials flow: This is an OAuth 2.0 grant type where applications request access tokens directly without user intervention. Used when the client is also the resource owner, it authenticates the application using its client ID and secret. Suitable for server-to-server authentication, the returned access token grants access to specific, predefined scopes.
  • Resource owner password credentials: This is an OAuth 2.0 grant type in which the resource owner (typically the user) provides their service credentials (username and password) directly to the client application. The client then exchanges these credentials for an access token from the authorization server.
  • Hybrid flow: Suitable for applications that can store client secrets, this flow enables immediate access to ID tokens alongside ongoing access to refresh tokens. 
  • Device authorization flow: This flow is suitable for input-constrained devices that connect to the internet. Instead of authenticating the user directly, the device asks the user to go to a link on their computer or smartphone and authorize the device.
  • PKCE flow: An extension to the OAuth 2.0 Authorization Code flow, it is designed to enhance its security when used with public clients, like mobile applications or single-page web apps. These clients can’t reliably store client secrets.

The main difference between the authorization code flow and the client credentials flow is that the client credentials flow relies on application authorization rather than involving the user.

OAuth flows use 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.

Note that OAuth 2.0 is focused solely on authorization, while OpenID Connect (OIDC) supports authentication and authorization. OIDC has more stringent standards and integrated security features than OAuth2.

This is part of an extensive series of guides about access management.

The OAuth Authorization Process

To add more context, the general OAuth authorization process, which is relevant for all OAuth flows, works as follows. Each OAuth flow may implement these steps a bit differently based on the application’s needs and security requirements.

  1. The user shows intent: This is usually the point where the user clicks on a “Login” button or accesses a restricted resource that requires them to sign in. It signifies the user’s intent to initiate the OAuth process to grant access to their data.
  2. The consumer gets permission: Here, the client (often referred to as the consumer) prepares an OAuth request and directs the user to the OAuth authorization server. The server will usually show a consent screen, listing the kinds of data the client wants to access and what actions it wants to perform.
  3. The user is redirected to the service provider: The user is redirected to the authorization server’s UI, often a web page, where they must log in and approve the permissions requested by the client.
  4. The user gives permission: Once the user has authenticated, they give consent for the permissions requested. This is usually done by clicking an “Approve” button on the authorization server’s UI.
  5. The consumer obtains an access token: After successful authentication and approval, the user is redirected back to the client with an authorization code (or directly with an access token in case of Implicit Flow). The client then exchanges this code for an access token by making a server-to-server request.

The consumer accesses the protected resource: Finally, the client uses the acquired access token to access the protected resources hosted by the resource server. Depending on the OAuth flow, this token can be short-lived and optionally refreshed.

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. The implicit flow is suitable for applications that access APIs and cannot store sensitive information.

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

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. 

Related: OAuth Grant Types

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.

See Additional Guides on Key Access Management Topics

Together with our content partners, we have authored in-depth guides on several other topics that can also be useful as you explore the world of access management.

ABAC

Authored by Frontegg

RBAC

Authored by Frontegg

User Management

Authored by Frontegg