Dive Into OAuth Grant Types and OpenID Connect Flows
What to know more about flows used by OAuth and OIDC? Here you can find details of all flows used by both standards alongside their possible use cases.
Join the DZone community and get the full member experience.Join For Free
In my last article, you could read about the differences between OAuth, SAML, and OpenID Connect. Today I want to continue the topic. We will dive deeper into the processes of authentication and authorization offered to us by respectively (OpenID Connect) and (OAuth). However, we will start with a few words about the naming conventions in both.
GrantTypes vs Flows — Semantic Difference
In general, both terms are correct and can be used simultaneously. Both of them describe the same thing – a process of obtaining an Access Token. Just keep in mind that the term “Grant Type” is more strongly related to OAuth, while the term “Flow” is more related to OpenID Connect. As a side note, I can add that the term “Flow” rarely occurs in the OAuth specification.
You can encounter the term “specification” in relation to the processes mentioned above, so just remember that it is just another term to describe the same thing.
OAuth Grant Types
The original OAuth specification describes four different grant types: Authorization Code, Implicit(or Implicit Flow), Resource Owner Password Credentials (or Password Grant), Client Credentials. Additionally, we can also count Refresh Token as a grant type it has its own separate process relying on exchanging refresh tokens on access tokens.
Over the years a few things have changed. Password and Implicit grants became obsolete – not in the way that they are not supported, they just stopped being recommended anymore, and using them is considered a bad practice.
On the other hand, we got a new grant type - Device Code and security extension called – Proof Key for Code Exchange (PKCE). Moreover, OAuth provides the mechanism of creating new custom grant types, so if you have enough determination you can create your own grant type.
Now we can move on to describe each of the currently defined grant types in detail:
Authorization Code is a grant used to obtain access and refresh tokens, based on exchanging authorization code for a token. It is optimized for confidential clients but can also be used with public.
It is one of the grants which require redirection to work, so the client must be able to interact with the resource owner's user-agent (typically a web browser) and receive incoming requests (via redirection) from the authorization server. The authorization code itself will be embedded in a redirect URL from the resource owner’s agent and used to request an access token.
What is notable here is that the resource owner's credentials are never shared with the client. Moreover, the direct transmission of the access token to the client without passing it through the resource owner's user-agent eliminate the possibility of exposing our valuable tokens to unwanted agents.
This grant type is the simplified version of the Authorization Code grant. It is optimized for clients running in the browser. It imminently returns an access token, omitting the authorization code exchange step.
Implicit grant can improve the responsiveness and efficiency of some clients because it reduces the overall number of steps needed to achieve the final result. On the other hand, this grant type does not authenticate the client so the token can be exposed to any other agent with access to the resource owner's user app.
It means that we can expose our app to many new security attacks. It is the reason why Implicit is no longer recommended in favor of Authorization Code grant with PKCE extension. What is more, OAuth 2.0 Security Best Practice recommends against using the Implicit entirely.
Resource Owner Password Credentials
In my opinion, it is the simplest grant type around because it requires only one request to retrieve an access token. It works by exchanging user credentials (for example: username and password) to obtain an access token. This grant type can eliminate the need for the client to store the resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.
Previously it was believed that it should be used only in cases when there is a high degree of trust between the resource owner and the client, and when using other grant types in not possible. However, because of direct access to user credentials, this grant type is not recommended to be used at all anymore.
In fact, the latest OAuth 2.0 Security Best Practice disallows the Resource Owner Password Credentials grant entirely.
It is a grant type used to obtain an access token without user context - using only its credentials. It is also the best grant in case when the authorization scope is limited to the protected resources under the control of the client, or when protected resources were previously arranged with the authorization server. Moreover, this grant requires usage of confidential clients.
This grant type is probably one of the most crucial ones because it allows the client to achieve continuous usage of a valid token without further interaction with the user. As you might expect, it works by exchanging a refresh token for an access token that has expired.
In accordance with OAuth Spec, a refresh token is a token issued, optionally, to the client by the Authorization Server alongside an access token. It is a string representation of the authorization granted to the Client by the Resource Owner and usually is opaque to the Client. They are also intended to be used only with Authorization Servers and are never sent to Resource Servers.
Device Authorization Grant
Device Authorization Grant or Device Flowis an extension to OAuth 2.0 in form of singleRFC 8628. Its main point is to add the possibility to obtain an access token for devices with no browser or with limited input capabilities.
This grant has a few requirements for devices it is expected to be used on:
1. The device is already connected to the Internet.
2. The device is able to make outbound HTTPS requests.
3. The device is able to display or otherwise communicate a URI and code sequence to the user.
4. The user has a secondary device (for example smartphone) from which they can process the request.
Because this grant type does not require two-way communication between the OAuth client and the user agent on the same device (unlike other OAuth grant types), it can support several use cases that other grants are not able to cover. What is more, this is the only grant that requires using a secondary device to approve the access request.
However, this grant type is not intended to replace browser-based OAuth in apps on devices like smartphones. Those apps should use yet another grant specified in separate RFC.
Device Code was created as an extension grant in RFC 6749to play an important part in Device Authorization Grant, where it is used to exchange the previously obtained device code for an access token. When performing a request its URL “grant_type” parameter must be set to:
Proof Key for Code Exchange
Proof Key for Code Exchange or PKCE, was presented in RFC 7636. It is an extension to the Authorization Code grant type and aims to provide additional protection against CSRFand authorization code injection attacks.
Originally designed to protect the Authorization Code grant in mobile apps, PKCE turned out to be useful also for web apps that use a client secret and became a general recommendation in many other OAuth grant types.
It seems that we managed to cover all basic grant types from current OAuth standard, so we can move on to describing the grant types provided by OpenID Connect.
OpenID Connect Flows
Opposite to OAuth being the authorization protocol, OpenID Connect is the authentication one. In its current specification, we can find 3 grant types: Authorization Code Flow, Implicit Flow and Hybrid Flow.
The biggest difference between the flows comes in form of “place” where we get our Access Tokens – in case of Authorization Code we get them from Token Endpoint while in Implicit Flow we get them from Authentication Response and in Hybrid flow we can choose the source of our tokens.
Recommended use cases of particular flows are quite well described in specification so I will just paste the image from OpenID specification. Additionally, unlike OAuth, there were no major changes here so no grants are deprecated and all 3 are still recommended.
Moving on to a more detailed description of each flow:
Authorization Code FlowThis flow works by exchanging Authorization Code directly for an ID Token and an Access Token. Authorization Code can be obtained from Token Endpoint. Because we exchange data directly, we do not have to expose any details to malicious applications with possible access to the User Agent.
Furthermore, authentication itself can be done before exchanging code for a token. This flow is best suited for Clients that can securely maintain a Client Secret between themselves and the Authorization Server. When using the Authorization Code Flow, all tokens are returned from Token Endpoint.
Implicit FlowOpposite to Authorization Code flow here, we get our tokens from Authorization Endpoint. Here Access and Id Tokens are returned directly to the client, exposing them to any application with access to the end user’s Agent. Thanks to this direct return, this flow is best suited for Clients implemented in a browser. What is more, the Authorization Server does not perform Client Authentication and Token Endpoint is not used.
Hybrid FlowIt is the most complex of all three flows. Here, access token can be returned from both Authorization and Token Endpoints. It can also be returned from both of them at the same time, and what is pretty interesting the returned tokens are not guaranteed to be the same.
Because this flow is the combination of two previously mentioned, both Authorization and Token endpoints inherit some part of their original behavior. There are also differences here, mostly in the process of handling and validating ID Token.
I explained where the particular naming convention came from and why in most cases we talk about one and the same thing. I also described, with some details, all flows provided to us by both OAuth and OpenID Connect. I hope that this humble lexicon of flows will come in handy to you at some point or that you at least read something new and interesting. Thank you for your time.
Opinions expressed by DZone contributors are their own.