OAuth 2.0: Implicit Flow is Dead, Try PKCE Instead
There are a number of OAuth 2.0 flows that can be used in various scenarios. The Implicit flow was previously recommended for native, mobile, and browser-based apps to immediately grant the user an access token. In this post, we’ll learn why the Authorization Code flow (with PKCE) is the new standard for more secure authorization for these types of apps.
With the release of Postman v7.23, we announced support for Proof Key for Code Exchange, better known as PKCE (pronounced “pixy”). Let’s walk through a few of the common OAuth 2.0 flows in Postman before we get into why PKCE has become an IETF-recommended authorization flow.
“Security and privacy controls are ‘must-have’ features these days. When thinking about all the nuances of protecting resources and access tokens, enable only the grant types necessary and implement the strictest controls available.” –Daniel Katz, Senior Product Manager at Ping Identity
What is OAuth?
Related: What is API authentication?
When people talk about OAuth, they typically mean OAuth 2.0—an authorization framework that describes how unrelated services can grant access to resources. It’s an open standard used by apps, APIs, and other services over HTTPS.
One example of OAuth is when you log into a website and are prompted to log in using an unrelated website’s login. The other website authenticates you and gives you permission to access this website.
OAuth decouples authentication from authorization, by relying on a third party to grant an access token. Doing this reduces your attack surface since your client secret is not required to access certain resources.
“Many luxury cars today come with a valet key. It is a special key you give the parking attendant and unlike your regular key, will not allow the car to drive more than a mile or two. Some valet keys will not open the trunk, while others will block access to your onboard cell phone address book … OAuth is about giving access to your stuff without sharing your identity at all (or its secret parts).” (OAuth.net)
OAuth 2.0 has different grant types for various scenarios. Here are a few of them.
- Password: for logging in with username and password
- Client credentials: for when a user is not present
- Authorization Code: for mobile and web apps
- Implicit: historically used for single-page JavaScript apps where secrets cannot be securely stored
Let’s take a look at two commonly used grant types, Authorization Code and Implicit.
What is the Authorization Code flow for OAuth?
One widely used grant type is the Authorization Code flow. JSON web token (JWT) is one standard that uses this type of grant.
Instead of requesting tokens directly from your API, the Authorization Code flow protects a client secret by redirecting a request for a token through an Authorization Server.
The Authorization Server authenticates a user and approves their access to a resource by providing a temporary authorization code. A token can then be requested using your credentials along with this authorization code.
The authorization code offers an additional layer of security. However, this grant requires sending the client secret to request the access token. The OAuth service provider can then verify the request is coming from a legitimate client, instead of an attacker who has intercepted the authorization code.
What is the Implicit flow for OAuth?
The Implicit grant was previously recommended for native and browser-based applications, whose client secrets cannot be revealed on the frontend:
- Native mobile apps, whose client secrets cannot be securely stored since decompiling the app will reveal them
- Browser-based apps, like single-page apps (SPAs), whose client secrets cannot be securely stored because the app’s source code is available to the browser
For these scenarios, the Implicit grant is a simplified Authorization Code flow that directly issues an access token without authenticating the client.
Note: Do not use the Implicit flow for authorization. Instead, use the Authorization Code flow (with PKCE) for your native, mobile, and browser-based apps.
What is PKCE?
“PKCE (Proof Key for Code Exchange) is an extension to the Authorization Code flow to prevent certain attacks and to be able to securely perform the OAuth exchange from public clients.” (OAuth.net)
For native and browser-based JavaScript apps, it is now widely considered a best practice to use the Authorization Code flow with the PKCE extension, instead of the Implicit flow.
This flow is like the regular Authorization Code flow, except PKCE replaces the client secret used in the standard Authorization Code flow with a one-time code challenge. This means the client app doesn’t have to store a client secret.
How to use PKCE in Postman
Earlier, we saw another layer of security for OAuth public clients using the following elements:
- Code verifier: a cryptographically random string used to correlate the authorization request to the token request
- Code challenge: derived from the code verifier sent in the authorization request, to be verified against later
- Code challenge method: what was used to derive code challenge
Now we’re going to set up Authorization Code flow (with PKCE) in Postman.
- In Postman, under the Authorization tab of any request, select
OAuth 2.0
. - Click Get New Access Token.
- Select a Grant Type of
Authorization Code (With PKCE)
. - The Code Challenge Method can be either
SHA-256
orPlain
. - You can also optionally provide a custom Code Verifier.
Click Request Token and walk through the authorization process to generate a new token. The access token can then be used according to your specific API’s documentation.
Try it out in Postman
If you want to try out some examples in Postman, check out our template walking through various OAuth 2.0 flows.
Additional Resources
If you work with native or browser-based applications, the PKCE extension to the Authorization Code flow enables a more secure OAuth exchange from public clients.
If you’re new to the world of OAuth and PKCE, check out these helpful resources to get started:
- OAuth 2 Simplified from Aaron Parecki
- PKCE Example on the OAuth 2.0 Playground from Okta
- Call API using Authorization Code flow with PKCE from Auth0
Possible correction in section about implicit flow:
> For these scenarios, the Implicit grant is a simplified Authorization Code flow that directly issues an access token without authenticating the user.
Should be:
> …without authenticating the client.
Thanks for article, BTW. First time I hear about PKCE flow, it wasn’t around when I was dealing with OAuth2, but I always thought there was something missing in the implicit flow. 🙂
Good catch, Danilo! Updated.
I noticed in your screenshot you have a client secret entered. Is the client secret required with PKCE or not?
I have the same question as Byron, is the client secret required for Auth code + PKCE? In my initial testing, I was unable to get this flow to work w/o the client secret.
Ok, so I’m trying to use this setup, but the whole point of PKCE is NOT to use client secret, or at least that’s what my client requires. Our implemented flow works fine without it, but Postman just refuses to cooperate with me here and I have no idea how to set this up for testing. I’m missing a grant type, I’m missing a possibility to use POST instead of GET… and I miss the omission of client secret.
I have the same question as Byron and Eric. Based the PKCE concept, the “Client Secret” should not be used for Auth code + PKCE. My web app in Okta with PKCE does not provide the “Client Secret” value at all. I tried to use Postman to get the access token by using the OAuth2.0, it does not work work for me. Can postman update that OAth2.0 screen to remove that required “Client Secret” field to avoid confusing? or is it optional or other way to make it work for web type with PKCE? Thanks in advance.
How can I test this flow when the service requires acr_values included in the authorize and token requests?
If you are confused if you need client secret or not, you need it in Postman, because Postman is considered a confidential client, and the client secret is typically used for confidential clients to authenticate themselves during the authorization process. In your actual mobile app, you should not include or use a client secret, as it can be more easily exposed and compromised.
As far as I know PKCE was an addition to the Authorization Code Flow originally for mobile apps. In web application there is used backchannel to protect the ClientSecret. The state diagram here is wrong for the web application – once the Client (frontend) receives the code from Authorization server, it sends it to its backend (Your Api), which in turn makes the call to Authorization server, adding the ClientSecret. Then it validates the response from Authorization server and then returns the tokens to the client (frontend).
I’m encountering with this error: https://github.com/smolblog/oauth2-twitter/issues/9
Please contact our support team at http://www.postman.com/support, and they’ll be able to help you.
Hmm, thanks for such a great article but I think this article shies away from the topic of client secret and/or certificate. I have been working on this flow and I am able to get Id token, refresh token and profile token without client secret. But I am not getting an access token unless I am willing to share my client secret or certificate which I need to upload. So, Auth flow with PKCE won’t return access token without either. I think the whole point is not to use client secret.
https://learn.microsoft.com/en-gb/entra/identity-platform/v2-oauth2-auth-code-flow