When To Use Which (OAuth2) Grants and (OIDC) Flows
Update(07/01/2019): This is by far my most popular post. I’ve continued to update this article based on feedback and things that I have noticed. I’m trying to keep it relevant.Please leave feedback in the comments section.
Update (07/9/2020): There is an OAuth 2.1 spec in draft that makes several notable changes. I’ve called these out below. There are also several new specs in the OAuth2 family of specs (RFC) that provide additional guidance. I also call these out below. Checkout this link for more information. Or, see the draft spec here.
Update(05/27/2024): At some point in the past two years, this became my first post to exceed 100K views. I recently posted a new article about RFC9068 which standardizes the OAuth2 Access Token on JWT along with a standard set of claims to include. The information in this post is still generally valid. Note, the OpenID Connect Authorization Code Authentication Flow is generally recommended for most common use cases involving authentication of a human user. The details differ depending on the use case — read below.
Update(08/03/2024): Added additional guidance regarding the OAuth2 Client Credentials Grant. Primarily, to clarify that this grant should not be with a client application running in a browser, from a native desktop application, or a native mobile app.
If you have been following my SAML2 vs JWT series lately, you are no doubt familiar with the OAuth2 and OpenID Connect (OIDC) specifications . The OAuth2 specification defines several authorization grants that can be used to coordinate authentication of a user and grant access to resources owned by that user. Of course, in the earlier OAuth2 post, we discussed how OAuth2 is an authorization protocol that doesn’t define the specifics of how the authentication occurs, but any complete implementation will support a variety of authentication mechanisms. These grants include:
- Authorization Code Grant
- Implicit Grant (deprecated in OAuth 2.1 draft)
- Resource Owner Password Credential Grant (deprecated in OAuth 2.1 draft)
- Client Credential Grant
The OIDC spec adds to this list by providing a set of authentication flows including:
- Authorization Code Flow
- Implicit Flow
- Hybrid Flow
The OAuth2 family of specs define several extension grants (that we explore here) that we will explore when to use in a future post.
We explored relatively generic use cases in my earlier blog posts; it may have left you wondering when each of these mechanisms should be used. When I was first exposed to these concepts several years ago, I struggled with that as well.
So, in this blog post, we are going to explore exactly when each of these should be used — including some instances of where these could be used, but maybe cause more problems then they solve. I covered some of this information in my earlier posts, but that wasn’t the primary focus and the discussion is incomplete.
Another note, worth mentioning, before diving into the details is that most Identity Providers (OAuth2 Authorization Servers and OIDC OpenID Providers) now offer libraries and SDKs that allow this functionality to be used without being aware of all the low-level details. Regardless of whether such a library is available for your IdP, the supported features of your IdP will dictate more than anything else what OAuth2 and OIDC features are used — choose wisely with an understanding of your expected use cases.
The recommendations in this post are briefly summarized here. For each of the following client types (where end user authentication is required), the following grants and flows should be used (generally, with a preference towards the OIDC option, if available).
Web Application (with dedicated server-side component): OAuth2 Authorization Code Grant (with Confidential Client), OIDC Authorization Code Flow (with Confidential Client). For the browser components of this, see this draft spec for additional guidance
Desktop Native Application: Authorization Code Grant (with Public Client and PKCE), OIDC Authorization Code Flow (with Public Client and PKCE). See RFC8252 for more information.
Mobile Native Application: Authorization Code Grant (with Public Client and PKCE), OIDC Authorization Code Flow (with Public Client and PKCE). See RFC8252 for more information.
SPA App: In OAuth2 RFC, OAuth2 Implicit Grant, OIDC Implicit Flow (Authorization Code Grant or OIDC Authorization Code Flow with Public Client could be used, note commentary below). In the OAuth2.1 RFC, Authorization Code Grant or OIDC Authorization Code Flow with Public Client. This blog post goes deep on the topic. This one provides yet more detail. See this draft spec for additional guidance.
Javascript application: In OAuth2 RFC, OAuth2 Implicit Grant, OIDC Implicit Flow (Authorization Code Grant or OIDC Authorization Code Flow with Public Client could be used, note commentary below). In the OAuth2.1 RFC, Authorization Code Grant or OIDC Authorization Code Flow with Public Client. See this draft spec for additional guidance.
Anytime you have a system that isn’t concerned with the end user identity (and just needs to authenticate the system), use the OAuth2 Client Credential Grant. This should primarily be machine-to-machine or system-to-system use cases where the end-user security context does not exist. Note, if an end user security context is available upstream, care should be taken to continue to extend as deep into the system as possible.
From a purely technical point of view, most of the OAuth2 grants and OIDC flows that support end user authentication can be made to work in just about any scenario, but there tend to be profound security (or lack thereof) implications to being creative in this fashion.
For the other grants and flows, read below.
OAuth2 Spec
The OAuth2 spec (Section 2.1) describes three types of clients:
- native applications (across a variety of devices including desktop, phone, tablet, etc) — typically, a public client.
- user-agent-based applications (JavaScript-based applications and SPA apps for our purposes) — typically, a public client.
- web applications (traditional web application architecture) — typically, a confidential client
Plenty of applications will not fit into exactly one of these categories. Individual situations will have to be evaluated on their own merits.
Any time we discuss resources below, this could be anything of value that is accessible on the network — data store, web application, API (my favorite example), static content, etc.
Things to Consider:
- Public versus confidential clients
- You own/control the app vs. third-party owns/controls the app
- Type of Client: Web Application, Native App, User-Agent-based app
- End user or application identity (or both)
- Desire to have a centrally-managed login workflow with a common look and feel.
Additional information about the mechanics of the OAuth2 grants can be found here.
OAuth2 — Authorization Code Grant
This is usually targeted at web applications or other systems that have a server-side component that can act as a Confidential Client (keep the client secret secure). The end result is that the end user and user agent do not see the OAuth2 Access Token or any other information that may be contained in the OAuth2 Authentication Response and allows for the client and the end user to be authenticated.
So, the Authorization Code Grant works great for the traditional Web Application architecture that has a dedicated server-side component. It can also work in most situations where there is a secure, server-side component that can act in the role of the Client.
With modern SPA apps, native mobile apps, and others this may not be the case — the server-side component may be a shared API Gateway for example that isn’t really meant to fill this role and may not be under your direct control (ergo, you don’t want it to know the client secret for your application). Thus, these are categorized as Public Clients. It’s also interesting to note that the “Client” terminology is used to describe the component closest to the end user in these scenarios, not the server-side component — as is the case with the “default” Authorization Code Grant example.
The OAuth2 specification does allow for a Public Client to use the Authorization Code Grant. Though, something is lost in terms of the level of security assurance when you are no longer authenticating the client (via client identifier and client secret). With this ability, it is possible to use the Authorization Code Grant with SPA apps and native mobile apps. Though, potential attack vectors are introduced without the client secret in play; to mitigate this issues, consider using the OAuth2 Proof Key for Code Exchange Spec that allows dynamic client secrets to be generated, which allows the Authorization Server to bind the authorization code exchange request to the original authorization code request.
When this grant is used (with a public client) by a native application, the prevailing methodology is to launch an external browser to handle the user’s interaction with the login workflow. Then, the native application itself does not see the user’s credential. A user-agent library that can handle the request/response processing could also be used, though this could result in the client application seeing the password.
Use Case: authentication of end users and access by client to a resource (possibly owned by the end user)
Used By: Web Applications (that have a server-side component that can keep the the client secret confidential), native apps (with a public client and PKCE)
Additional Use Cases: If you want to introduce refresh tokens to a situation where you wouldn’t otherwise have them (such as with the Implicit Grant) and the other requirements mentioned above are satisfied, this grant could potentially be used. Though, this is stated as a purely technical observation and is not a good practice or even necessarily secure.
OAuth2 — Implicit Grant
The Implicit Grant has the benefit of requiring only a single call to the IdP; however, it opens up security concerns that are not present in the other grants — namely, the user agent can now see the access token. This grant also lacks the ability to authenticate the the client, which the other grants can do — further introducing attack vectors that the authorization grants, which require a client secret, do not experience.
Refresh tokens are not supported.
Use Case: authentication of end users and access by client to a resource (possibly owned by the end user).
Used By: SPA Apps (and any other Javascript/User-agent-based app)
Additional Uses: Earlier in the life of OAuth2, the Implicit Grant tended to be recommended for native applications (especially native mobile apps). More recently, the Authorization Code Grant (with public client and PKCE) is typically recommended for use with native apps. Though, using the Implicit Grant is still technically feasible.
OAuth2 — Resource Owner Password Credential Grant
Like the Implicit Grant, this grant also has the benefit of only making a single call to the authorization server. It allows an application that is incapable of integrating with an interactive login (such as you get with the Implicit Grant and Authorization Grant). This gives the authorization server a great deal of flexibility in terms of the types of clients that can interact with it, but it also provides a mechanism for bypassing a standardized login workflow mechanism that can enforce things like two-factor authentication, forced password resets, and similar desirable identity features. From the perspective of a centralized identity stack, bypassing these features is counterproductive and undesirable; even if identity and access management functions are not centralized, this is still generally undesirable in the enterprise.
This authorization grant supports refresh tokens.
Use Case: authentication of end users and access by client to a resource (possibly owned by the end user)
Used By: any client that has access to the end user’s credentials, handles its own login workflow, and (because either you do not care or have no choice) is allowed to perform these tasks.
Additional Uses: Some sources recommend using this grant with your own native apps (rather than the authorization code grant with public client) since full access and control over the source code is ensured. In larger organizations, this may not be a viable assumption. Personally, I would use the authorization code grant with public client as described earlier in this article.
This grant can also be used in place of the Client Credential Grant in situations where a service account is used to represent the system or calling application. A larger strategy surrounding how applications will be represented within the identity stack is recommended before going down this path. Most modern identity providers (those that support OAuth2 and OIDC) will have functionality to represent an application similar to how traditional identity providers can represent a user.
OAuth2 — Client Credential Grant
This grant is different from the other three defined by the OAuth2 spec in that it provides for authenticating the application (or system) only, not an end user.
Refresh tokens should not be used with this grant, but the OAuth2 spec does not explicitly forbid the use (it states ‘a refresh token “should not” be included’). Some Identity Provider implementations return a refresh token with a Client Credentials Grant call to the Token Endpoint. You can see an example of this in my description of the Client Credentials Grant with Red Hat SSO v7.1 in this post.
Use Case: application or system identity being authenticated and then accessing a resource on a resource server. This is often described as machine-to-machine or system-to-system use cases. It is often seen with B2B Integration use cases.
Used By: Anything that can keep the client secret confidential, has no need for end user authentication, and needs to access a third-party resource. Please note, this does NOT include web application UIs running in a web browser, native desktop applications, or native mobile apps. Each of these should use some variation of the OIDC Authorization Code Grant. A server-side application server could act as an OAuth2 Client that uses the OAuth2 Client Credential Grant to make calls to remote services within the organization or hosted by third-parties. Note, that a grant/flow that preserves the end user security context is always preserved.
OpenID Connect Spec
Information about the OIDC Spec can be found here (earlier in the SAML2 vs. JWT series).
OIDC — Authorization Code Flow
This is the first of three OIDC authentication flows. The mechanics of this authentication flow is explored here.
Used By: All commentary made above regarding the OAuth2 Authorization Code Grant applies here. The details won’t be repeated here.
OIDC — Implicit Flow
The mechanics of this authentication flow are explored here.
Used By: All commentary made above regarding the OAuth2 Implicit Grant applies here. In addition, there is a choice of whether or not an access token is requested to access a backend resource (response_type of “id_token” or “id_token token). If your requirements include accessing a resource, then use “id_token token”. If end user authentication is the only requirement, “id_token” can be used.
OIDC — Hybrid Flow
The mechanics of this authentication flow are explored here.
As described in the OIDC series, this authentication flow is not used very often in the wild.
Used By: A client that
- needs a separate token for the front end and back end
- has bandwidth limitations that make a single call to the OP desirable, but still needs more OIDC functionality than is available in the Implicit Flow.
Additional thoughts:
- Whenever possible, use OIDC instead of pure OAuth2.
- For most application developers or architects, this information will be strictly academic or help drive requirements surrounding which IdP can be utilized. The choice of IdP and its resulting capabilities will drive design decisions in the identity space more than anything else. Likewise, most IdP vendors will have already created libraries across the various popular platforms for application development. Thus, eliminating the need for the application developer needing to address these details.
- If using an IdP’s OAuth2 implementation, it’s a near certainty that proprietary features have been added to the implementation to add reliability, security, and completeness to the solution. The OAuth2 spec by itself does not describe the complete solution.
- Even with the OIDC spec, the login workflow (including prompting for credentials, submission of the credentials and validation of the credentials) are not explicitly defined. It is possible to use SAML2 Browser Profile, WS-Federation, or another authentication mechanism to authenticate the user or implement a federation relationship (that authenticates the end user).
- Whenever an end user is being authenticated, try to use an interactive login that serves up the login workflow (this can be done with the OAuth2 Authorization Code Grant, OAuth2 Implicit Grant, OIDC Authorization Code Flow, or OIDC Implicit Flow). This promotes a common look and feel and maintains centralized control over the login process.
- Whenever you use OAuth2 or OIDC, follow the advice given in the OAuth2.0 Security Best Current Practices draft.
- Per OAuth2.1 draft, whenever the Authorization Code Grant or OAuth2 Authentication flow is used, PKCE must be used.
- OAuth2.1 puts additional restrictions on the use of Refresh Tokens with Public Clients.
Some additional information specific to individual IdP vendors:
- Azure Active Directory
- ADFS OIDC use and OAuth2 use
- Ping Federate (and here)
Image: Architectural Flow / Kevin Dooley