Articles

OAuth 2.0 Grant Types: Which Flow Should You Use?

OAuth 2.0 grant types are the flows apps use to get access tokens. Authorization code with PKCE, client credentials, device flow — and when to use each.

Chisato Chisato · · 5 min read
A digital security shield with circuit traces

A grant type — often called a flow — is the sequence of steps an application follows to obtain an access token from an OAuth 2.0 authorization server. The framework defines several because applications differ: a server-side web app can keep a secret, a single-page app cannot, and a smart TV doesn’t even have a keyboard. Picking the right grant type is the first real decision you make when integrating OAuth 2.0, and picking the wrong one is one of the most common ways integrations end up insecure.

The good news is that the decision has gotten simpler over time. Two of the original grants are now deprecated, and for anything involving a user, the answer is almost always the same: authorization code with PKCE.

Authorization code with PKCE: the default

The authorization code grant is the flow behind every “Sign in with Google” button. The client redirects the user’s browser to the authorization server, the user approves the request, and the server redirects back with a short-lived, one-time code. The client then exchanges that code for an access token in a direct server-to-server call.

PKCE (Proof Key for Code Exchange, pronounced “pixy”) hardens this exchange. Before redirecting, the client generates a random secret, hashes it, and sends the hash along as a code_challenge. When exchanging the code for a token, it sends the original secret as the code_verifier. The authorization server checks that the hash matches — so an attacker who intercepts the authorization code still can’t redeem it, because they never saw the verifier.

PKCE was originally designed for mobile apps, which can’t hold a client secret safely. Current guidance goes further: use it for every client, including confidential server-side ones, because it costs nothing and closes code-interception and code-injection attacks. The full flow is walked through step by step in our OAuth 2.0 explainer.

Use this grant whenever a human is present: server-rendered web apps, single-page apps, and native mobile or desktop apps.

Client credentials: machine to machine

Not every API call has a user behind it. A nightly billing job, a microservice syncing data with another service, a monitoring agent pushing metrics — these act on their own behalf. The client credentials grant covers this case: the client authenticates directly to the token endpoint with its client_id and client_secret (or a signed assertion) and receives an access token. No redirect, no consent screen, no user.

The resulting token represents the application itself, and any scopes attached describe what the service may do. This is the standard way to secure service-to-service calls against a REST API, and the tokens involved are commonly JWTs so the receiving API can validate them without a network hop.

Because a client secret is involved, this grant belongs only in environments that can keep one — servers and workloads, never browsers or installed apps.

Device authorization: TVs and CLIs

Some devices can make HTTPS requests but are miserable to type on. The device authorization grant solves login for smart TVs, game consoles, and command-line tools. The device asks the authorization server for a device code and a short user code, then displays instructions: “Visit example.com/activate and enter code WDJB-MJHT.” The user completes login and consent on their phone or laptop, while the device polls the token endpoint until approval lands, then receives its access token.

If you’ve ever activated a streaming app on a TV, or run a CLI that printed a URL and a code, you’ve used this flow.

The refresh token grant

Access tokens should be short-lived — minutes to an hour — which raises the question of what happens when one expires. The refresh token grant answers it: alongside the access token, the authorization server can issue a longer-lived refresh token, and the client exchanges it for a fresh access token without involving the user again.

Refresh tokens are powerful credentials and deserve care: store them server-side where possible, and prefer rotation, where every use issues a replacement and invalidates the old one. Rotation means a stolen refresh token gets detected the moment both the thief and the legitimate client try to use it.

The deprecated flows: implicit and password

Two grants from the original 2012 specification are now considered mistakes to avoid in new systems.

The implicit grant returned the access token directly in the redirect URL fragment, skipping the code exchange entirely. That put tokens in browser history, referrer headers, and anywhere else URLs leak, with no way for the client to prove itself. It existed because browsers once couldn’t make the cross-origin token request — a limitation CORS erased years ago.

The resource owner password credentials grant had the user type their password into the client application, which forwarded it to the authorization server. That defeats the entire point of delegation — the third-party app sees the password — and it breaks multi-factor authentication and passkeys, which need the real login page. If a vendor’s API asks you to collect user passwords, that’s a red flag, not a flow.

Which grant should you use?

Your situationGrant type
Web app with a backendAuthorization code + PKCE
Single-page app (browser only)Authorization code + PKCE
Mobile or desktop appAuthorization code + PKCE
Service or job with no user involvedClient credentials
Smart TV, console, or CLI loginDevice authorization
Keeping sessions aliveRefresh tokens (with rotation)
Tempted by implicit or password grantAuthorization code + PKCE instead

The pattern is hard to miss: if a user is present, use authorization code with PKCE; if not, use client credentials; if the device can’t handle a browser redirect, add the device flow on top.

OAuth 2.1: fewer choices, safer defaults

The IETF has been consolidating this hard-won guidance into OAuth 2.1, a cleanup of the specification that was still working through the draft process as of early 2026. It doesn’t invent new mechanics — it removes the implicit and password grants outright, makes PKCE mandatory for the authorization code flow, and folds in the security best practices that implementers already follow. In other words, the decision table above is OAuth 2.1 in spirit; the spec just makes it official.

Note that grant types answer only the authorization question. If what you actually need is login — knowing who the user is — that’s OpenID Connect layered on top, and the differences are covered in our comparison of OAuth, OIDC, and SAML.

The takeaway

Grant types are just the different paths to an access token, matched to different kinds of clients. Modern OAuth needs only three: authorization code with PKCE when a user is present, client credentials for machine-to-machine calls, and device authorization for screens without keyboards — with refresh token rotation keeping sessions alive quietly. The implicit and password grants are legacy; if a tutorial or vendor steers you toward either, it’s out of date.

Chisato Chisato · · 5 min read

What Is Session Fixation?

Session fixation tricks a victim into using an attacker-known session ID, so logging in hands the attacker an authenticated session too.

#Security #Authentication #Web Development
Chisato Chisato · · 4 min read

The OAuth PKCE Flow Explained

PKCE hardens the OAuth authorization code flow against interception, and is now recommended for every client type, not just mobile and single-page apps.

#Security #Authentication #Web Development