SecLab
Authentication & SessionconceptDifficulty 3/520 min

Choosing the right OAuth flow for the client

Objective: After this lesson you can pick the OAuth flow for any client, and explain why three flows were deprecated.

V10API2:2023A07:2025RFC 9700
Step 1 of 4 · read6 min

One question picks the flow

OAuth 2.0 has many flows, and documentation usually presents them as a menu. Reality is far simpler: RFC 9700 (the current BCP) deprecated most of them, so the real question is one: can this client keep a secret.

Client typeCan keep a secret?Flow

SPA, mobile app, desktop app | No | Authorization Code + PKCE | Web app with a backend | Yes | Authorization Code + PKCE + client secret | Machine-to-machine, no user | Yes | Client Credentials | TV, keyboard-less device | No | Device Authorization Grant |

That is all. Those four rows cover every client you will meet.

Three deprecated flows, and knowing why matters because you will meet them in old code:

(1) Implicit (response_type=token) — returns the access token directly in the URL fragment. It existed because in 2012 CORS was not widespread, so a SPA could not call the token endpoint. The problem: the token is in a URL, so it lands in browser history, in Referer, in proxy logs. And there is no refresh token, so either the token is long-lived (bad) or the user re-authenticates constantly.

(2) Resource Owner Password Credentials (ROPC) — the client takes a username and password and exchanges them for a token. It defeats OAuth's entire purpose: the user hands their password to the client rather than the provider, so there is no MFA, no consent screen, and every client must be absolutely trusted.

(3) Authorization Code without PKCE — not "deprecated" so much as PKCE became mandatory for every client, including confidential ones. The reason: PKCE stops authorization code interception, and that threat exists for confidential clients too (for instance through a loosely registered redirect URI).

What PKCE solves, briefly: the authorization code travels through the browser, so it can be intercepted. PKCE makes the client prove it is the same client that started the flow, by sending a code_verifier matching the code_challenge it sent at the start. An intercepted code becomes useless because the interceptor has no verifier.

View path

Comments

Join the discussion
Sign up to comment

Commenting needs an account with at least one completed lesson. That condition is what keeps this thread worth reading: every point belongs to someone who can be asked back, and reputation accrues over time.

Sign upSign in

You can still read every comment below without an account. Signing in brings you back to this exact spot, not to the top of the page.

Loading comments…