Pick the correct OAuth 2.0 grant
A grant type is the path an OAuth client takes to obtain an access token. The right one depends on what the client is: a web app that can redirect a user, a single-page or mobile app that cannot keep a secret, a backend service acting on its own behalf, or a constrained device like a TV. This reference describes each grant with its step-by-step flow and the security notes that matter, flagging which grants OAuth 2.1 keeps and which it removes.
Grant types at a glance
| Grant | User involved? | OAuth 2.1 status | Best for |
|---|---|---|---|
| Authorization Code + PKCE | Yes | Recommended | Web, mobile, SPA |
| Client Credentials | No | Recommended | Machine-to-machine |
| Device Authorization | Yes (on separate device) | Retained | TVs, CLIs, IoT |
| Refresh Token | Indirectly | Retained | Renewing access |
| Implicit | Yes | Removed | — (do not use) |
| Resource Owner Password | Yes | Removed | — (legacy only) |
How the redirect-based flow works
In the Authorization Code flow, the client redirects the user to the authorization server’s /authorize endpoint with its client_id, redirect_uri, scope, state, and — with PKCE — a code_challenge derived from a random code_verifier. After the user consents, the server redirects back to the client with a short-lived code. The client then POSTs that code plus the original code_verifier to the /token endpoint and receives the access token (and usually a refresh token).
The state parameter is a CSRF guard: the client generates it, embeds it in the redirect, and verifies it on return. The PKCE code_verifier is a per-request secret: even if an attacker intercepts the code in the redirect, they cannot exchange it without the original verifier.
Client Credentials flow
The Client Credentials grant skips the user entirely. The backend service posts its client_id and client_secret (or a signed JWT assertion) directly to /token and receives an access token scoped to its own permissions. There is no redirect and no refresh token in the canonical form.
Device Authorization
The device (a TV, a CLI tool, a console) calls /device_authorization and receives a device_code and a short URL it displays to the user. The user opens the URL on a phone or computer and approves. Meanwhile the device polls /token with the device_code until it gets the access token or the code expires. This decoupled flow means no browser redirect is needed on the constrained device itself.
Security guidance
Default to Authorization Code with PKCE for any user-facing client and enable
refresh-token rotation with reuse detection so a stolen refresh token can be
revoked across its whole token family. For browser-only apps, consider a
backend-for-frontend (BFF) that keeps tokens server-side rather than in
JavaScript. Always validate state on return, use S256 (never plain) for the
PKCE challenge, and scope tokens as narrowly as the task allows. Treat anything
that puts a long-lived token in the browser URL or fragment as a security
red flag — this is exactly what made the Implicit grant dangerous.