OAuth 2.0 has at least 4 different flows for different use cases. Find out which flow you should use to secure your app.
We learned how OAuth 2.0 works in general in What on Earth is OAuth? and learned how to securely store access tokens in the front end. In this post, we'll learn which OAuth 2.0 flow you should use based on what you're building.
In general, the OAuth 2.0 flow looks like this diagram below (if you're not familiar with the OAuth 2.0 Flow below, check our explanation here).
- Step 1: The website requests authorization for Albert. Albert is being redirected to Google's site to log in.
- Step 2: Google's site returned with an Authorization Grant. This is the part that has several different cases based on which flow you're using.
- Step 3-4: Depending on the flow, the client will have a way to exchange this Authorization Grant with an access token, and sometimes a refresh token
- Step 5-6: The website uses the access token to access resources.
As mentioned above, there are 4 common OAuth 2.0 Flows:
- Authorization Code Flow
- Authorization Code Flow with Proof Key for Code Exchange (PKCE)
- Client Credentials Flow
- Device Code Flow
Different apps should use different flows based on whether or not the app can hold secrets securely.
- Web Server Apps and Command Line Scripts: Use Authorization Code Flow
- Single Page Apps and Mobile Apps: Use Authorization Code Flow with PKCE
- Server-to-Server API Calls : Use Client Credentials Flow
- TV Apps and other apps on input-constrained devices: Use Device Code Flow
Web Server Apps are apps that are running on a server where the source code is not publicly exposed.
Requirements: Your app needs to be able to hold a Client Secret securely in the back end server.
- ✅ Your app runs on a server (Node.js, PHP, Java, .NET): Your server code is not publicly exposed and you can put secret keys in environment variables without it being visible to users of the application.
- ❌ React-only website: React is a SPA framework, your code is publicly exposed, and therefore cannot hold secrets securely, even if you put secrets in .env files.
- Step 1-4: User clicks Sign in with Google, and get redirected to Google's Site to authenticate.
Step 5: When the user successfully authenticated, Google will redirect the user back to your website, and include an
authorization_codein the redirect URL. For example:
https://mysite.com/redirect ?code=ABCDEFGHIJ12345 &state=abcde123abc
Step 6-9: With the code above and a Client ID + Client Secret that you get from Google when registering an application, you can request for an
access_tokenfor the user that you can then use to fetch data.
See the full spec at RFC 6749 Section 4.1
- On step 3 , show the URL that the user should go to in their browser.
- Get your script to listen to a local port, for example,
http://127.0.0.1:8000and set the redirect URL to be
- On step 5 , the user's browser will redirect to
https://127.0.0.1:8000/redirect ?code=ABCDEFGHIJ12345 &state=abcde123abc
- Your script should then handle this
GETrequest, parse the
stateand proceed to step 6-9.
Single Page Apps (SPA) and Mobile Apps are not able to hold secrets securely because their source code is publicly exposed or can be decompiled.
The PKCE flow requires the app to generate a secret on the fly. This secret is generated at the beginning of the flow when the user started the login flow and then checked when exchanging authorization code with an access token.
This makes sure that the entity that is requesting to exchange the authorization code with an access token is still the same entity where the user requested to authenticate.
- Step 1: User clicks the login button in your app
Step 2: Generate a
code_challenge, then make an authorization request by sending the
code_verifier = "a cryptographic random string" code_challenge = base64url_encode(sha256(ascii(code_verifier)))
Step 3-5: The Authorization Server will save the
code_challengefor later and redirect the user to log in, then redirect to your app with an
Step 6 : Your app then sends the
authorization_codeto get an access token.
Step 7: The Authorization Server will check if the original
code_challenge == base64url_encode(sha256(ascii(code_verifier))). This is where it determines whether the entity that started this flow is the same one as the one that is currently requesting an access token. If yes, it returns the access token.
- Step 8-9 : Your app can now fetch data using the access token.
See the full spec at RFC 7636.
Here are some resources to help you generate a code challenge and verifier:
- See how to generate
For example, your back end server wants to call an API endpoint at Stripe to retrieve a list of payments. This is a machine-to-machine authorization, and there's no end-user authorization. In this case, Stripe is only trying to authorize your server to access the API endpoint. Since your server can also hold secrets securely, all you need for accessing the data is a Client ID and Client Secret.
- Step 1: Your server authenticates itself using its Client ID and Client Secret. Notice that this doesn't involve any user. This is because your server is acting as itself. (For example, your server is acting as Hello Merchant that you registered to Stripe).
- Step 2: If the Client ID and Client Secret checks out, you'll receive an access token.
- Step 3: Use the access token to fetch data.
See the full spec at RFC 6749 Section 4.4
It'll be horrible if you have to input your super-secure Google password to watch YouTube on your brand new smart TV, right? OAuth 2.0 Device Code Flow is designed so that you can authorize apps on an input constraint device by opening a URL and entering a code on your browser (on your phone/laptop).
Requirements: Your app needs to be able to display a URL and a User Code to the user. This can also be done by showing a QR Code.
- Step 1: User requests to log in on your TV App.
Step 2-3: Your TV App makes an authorization request to the Authorization Server (Google Accounts in this case) with your app's Client ID, and receive 3 things: a
user_code, and a
Step 4 : Your TV App now asks the user to go to the
verification_uriand enter the
user_code. You can optionally do this by asking the user to scan a QR Code that encodes both the
Step 5: Your TV App now requests an access token to the Authorization Server using the
client_id. If the user hasn't authenticated and allowed access to your app yet (they haven't gone to the
verification_uri), the Authorization Server will respond with an error
authorization_pending. Your TV App should keep on requesting until you get an access token.
Step 6: The user typed in the
verification_urion their phone or laptop, and entered the
- Step 7-8: The user is now redirected to Google's Login page where they can authenticate and allow your TV App to access certain data.
Step 9 : Google accounts now mark that your user has authenticated and allowed your app to access their data. The next time your app requested for an access token with the
device_code, Google Accounts will return an access token.
- Step 10-11 : Use the access token to fetch data.
See the full spec at RFC 8628 Section 3.4
This should help you pick which OAuth 2.0 flow you need for different use cases. We didn't go into the specific HTTP Request parameters that you should use, we will cover that next time.
This post is written by the team at Cotter – we are building lightweight, fast, and passwordless login solution for websites and mobile apps. If you're building a website, we have a ready-made solution that implements the flows above for you.
Sign in with Magic Link via Email, SMS, or WhatsApp on:
We referred to these articles and specs to write this post:
- The OAuth 2.0 Authorization Framework (RFC 6749)
- OAuth Grant Types
- OAuth 2.0 Device Flow Grant
- Authentication and Authorization Flows
If you need help or have any feedback, ping us on Cotter's Slack Channel! We're here to help.