OAuth Grant Types and Flows
OAuth Grant Types and Flows
https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth#oauth-flows
Implicit flow
The very first flow is what we call the Implicit Flow. The reason it’s called the implicit flow is because all the communication is happening through the browser. There is no backend server redeeming the authorization grant for an access token. An SPA is a good example of this flow’s use case. This flow is also called 2 Legged OAuth.
Implicit flow is optimized for browser-only public clients. An access token is returned directly from the authorization request (front channel only). It typically does not support refresh tokens. It assumes the Resource Owner and Public Client are on the same device. Since everything happens on the browser, it’s the most vulnerable to security threats.
Authorization Code Flow
The gold standard is the Authorization Code Flow, aka 3 Legged, that uses both the front channel and the back channel. This is what we’ve been talking about the most in this article. The front channel flow is used by the client application to obtain an authorization code grant. The back channel is used by the client application to exchange the authorization code grant for an access token (and optionally a refresh token). It assumes the Resource Owner and Client Application are on separate devices. It’s the most secure flow because you can authenticate the client to redeem the authorization grant, and tokens are never passed through a user-agent. There’s not just Implicit and Authorization Code flows, there are additional flows you can do with OAuth. Again, OAuth is more of a framework.
Client Credential Flow
For server-to-server scenarios, you might want to use a Client Credential Flow. In this scenario, the client application is a confidential client that’s acting on its own, not on behalf of the user. It’s more of a service account type of scenario. All you need is the client’s credentials to do the whole flow. It’s a back channel only flow to obtain an access token using the client’s credentials. It supports shared secrets or assertions as client credentials signed with either symmetric or asymmetric keys.
Symmetric-key algorithms are cryptographic algorithms that allow you to decrypt anything, as long as you have the password. This is often found when securing PDFs or .zip files.
Public key cryptography, or asymmetric cryptography, is any cryptographic system that uses pairs of keys: public keys and private keys. Public keys can be read by anyone, private keys are sacred to the owner. This allows data to be secure without the need to share a password.
Resource Owner Password Flow
There’s also a legacy mode called Resource Owner Password Flow. This is very similar to the direct authentication with username and password scenario and is not recommended. It’s a legacy grant type for native username/password apps such as desktop applications. In this flow, you send the client application a username and password and it returns an access token from the Authorization Server. It typically does not support refresh tokens and it assumes the Resource Owner and Public Client are on the same device. For when you have an API that only wants to speak OAuth, but you have old-school clients to deal with.
Assertion Flow
A more recent addition to OAuth is the Assertion Flow, which is similar to the client credential flow. This was added to open up the idea of federation. This flow allows an Authorization Server to trust authorization grants from third parties such as SAML IdP. The Authorization Server trusts the Identity Provider. The assertion is used to obtain an access token from the token endpoint. This is great for companies that have invested in SAML or SAML-related technologies and allow them to integrate with OAuth. Because SAML assertions are short-lived, there are no refresh tokens in this flow and you have to keep retrieving access tokens every time the assertion expires.
Device Flow
Not in the OAuth spec, is a Device Flow. There’s no web browser, just a controller for something like a TV. A user code is returned from an authorization request that must be redeemed by visiting a URL on a device with a browser to authorize. A back channel flow is used by the client application to poll for authorization approval for an access token and optionally a refresh token. Also popular for CLI clients.
We’ve covered six different flows using the different actors and token types. They’re necessary because of the capabilities of the clients, how we needed to get consent from the client, who is making consent, and that adds a lot of complexity to OAuth.
When people ask if you support OAuth, you have to clarify what they’re asking for. Are they asking if you support all six flows, or just the main ones? There’s a lot of granularity available between all the different flows.
Which grant should I use?
Consider a simple application, diagrammed above, which allows users to manage todos. Clients like a web browser or mobile app will access two different components: an OAuth platform to authenticate users and a Todo API to add, update, or delete todos.
An OAuth grant is a specific flow that results in an access token. Per the specification, a token is an opaque string without any structure. However, OAuth servers can choose their token format, and many use JSON Web Tokens, which do have internal structure. Some parts of the grant, such as error messages or expected parameters, are well defined. Others, such as the actual authentication process, are left as implementation details.
A grant authenticates the user or other entity, assembles appropriate permissions based on user roles, groups, and requested scopes, gathers the authorization data, and encapsulates those permissions from the authorization server in the form of an access token. Here’s an example of a token: mF_9.B5f-4.1JqM.
The token is often, but not always, sent to the client for later presentation to the resource server. In the diagram above, the mobile apps and browser on the left will be going through an OAuth grant in order to gain access to the Todo API.
In this context, which grant should you choose to send your users through? The core RFC, RFC 6749, defines a number of grants. It can be confusing to determine which is the best fit for your use case.
For most developers, there are really only a few questions to ask:
- Is there a human being involved?
- How long will the client need access to the protected resource?
Let’s tackle each question.
Is there a human being involved?
Whenever a user is involved, the best grant to use is the Authorization Code grant. This grant will be discussed in more detail below. Using this offers architectural flexibility around the final location of the access token as well as a better security profile. In general, you should pair the Authorization Code grant with PKCE.
In the todo application outlined in the diagram above, a human being is making the initial request to display todos in their application, so the Authorization Code grant should be used.
But let’s consider a different situation.
Suppose we extend the application with new functionality to remind our users of deadlines associated with their todos.
In that case, we need a reminder service which would run every day, see which todos were due, and send a reminder email. This service would still need to authenticate because we wouldn’t want anyone to be able to access our todos. But there is no user kicking off the request—perhaps its only a cron job.
That flow of permissions might look a little something like this:
When there is no human being starting the request, the correct grant to use is the Client Credentials grant. This grant should be used whenever you have service to service communication and want to leverage the client library support, centralized authentication, and security infrastructure of an authorization server.
How long will the client need access to the protected resource?
In general, access tokens are good for a short period of time (seconds to minutes). If the client can gain access to the resources it needs in that time, then all is well and good. However, sometimes the client needs access for the longer term. When the access token expires, the client can either ask the user to re-authenticate or it can use the Refresh grant.
This grant allows a client to transparently re-request a token with the same permissions without forcing the user to re-authenticate.
What about the other grants?
The other grants, such as the Device grant or the Resource Owner Password grant, should be used only when the use case calls for their specific functionality.
In general, use the Authorization Code grant if there is a human being involved and the Client Credentials grant if you are performing server to server communication.