Oauth 2.0 Grant Types

# OAuth 2.0 Grant Types Explained (Is PKCE One?)

6 min read
Table of Contents

List of Grant Types

Below is a table summarizing the different grant types in OAuth 2.0 along with brief descriptions and recommendations regarding their use:

Grant TypeDescriptionRecommendation
Authorization CodeThe most commonly used flow in OAuth 2.0. It involves the exchange of an authorization code for an access token. Suitable for server-side web applications and confidential clients.Recommended for web applications and confidential clients.
ImplicitDesigned for user-agent-based clients (e.g., browser-based JavaScript applications). Access token is returned directly to the client without an authorization code exchange.Deprecated due to security concerns.
Resource Owner Password CredentialsAllows the client to exchange the user’s username and password for an access token directly. Generally discouraged due to security implications and lack of federation support.Not recommended unless unavoidable legacy scenarios.
Client CredentialsEnables clients to directly exchange client credentials (client ID and client secret) for an access token. Typically used for machine-to-machine communication.Recommended for machine-to-machine communication.
Refresh TokenAllows clients to request a new access token without requiring the user to re-authenticate. It’s not a grant type but rather a mechanism for obtaining new access tokens.Recommended for long-lived sessions and offline access.

It’s important to note that while some grant types may be deprecated or discouraged due to security concerns or lack of use cases, their applicability can vary based on specific requirements and use cases. However, it’s generally recommended to adhere to best practices and use the authorization code flow whenever possible for enhanced security and flexibility.

How Each Grant Type Works

The table tells you which grant to pick. This section shows what each one actually does on the wire. Parameter names follow RFC 6749 and, for the device flow, RFC 8628.

Authorization Code with PKCE

Use it when a user signs in and your app acts on their behalf: server-rendered web apps, single-page apps and native or mobile apps. The client sends the user to the authorization server, the user logs in and consents, and the server redirects back with a short-lived code. The client then exchanges that code, over a direct back-channel request, for tokens.

With PKCE, the client first creates a random code_verifier and sends its hash as code_challenge in the authorization request:

GET /authorize?response_type=code
&client_id=my-app
&redirect_uri=https://app.example.com/callback
&scope=openid%20profile
&state=af0ifjsldkj
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256

When it redeems the code, the client sends the original verifier in the token request:

POST /token
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://app.example.com/callback
&client_id=my-app
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

An attacker who steals the code from the redirect cannot redeem it, because they do not have the verifier. OAuth 2.1 and current security guidance make PKCE mandatory for public clients and recommend it for confidential ones too. For the full step-by-step flow, see OAuth 2.0 Authorization Code Flow, Step by Step.

Client Credentials

Use it for machine-to-machine calls where there is no user: a backend service, a cron job or a CI pipeline calling an API as itself. The client authenticates with its own credentials and gets an access token directly, with no browser and no redirect:

POST /token
Authorization: Basic base64(client_id:client_secret)
grant_type=client_credentials&scope=reports.read

Because there is no user, the token represents the application, and the scopes you grant should be as narrow as possible. Only confidential clients that can keep a secret should use it. Never ship a client secret inside a browser or mobile app.

Device Authorization (Device Code)

Use it for devices that have no browser or an awkward keyboard: smart TVs, game consoles, CLI tools, IoT. The device asks the authorization server for a device code, shows the user a short user_code and a URL, and the user completes the login on their phone or laptop. Meanwhile the device polls the token endpoint:

POST /device_authorization
client_id=my-tv-app&scope=profile
-> { "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"user_code": "WDJB-MJHT",
"verification_uri": "https://example.com/device",
"interval": 5 }
POST /token
grant_type=urn:ietf:params:oauth:grant-type:device_code
&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
&client_id=my-tv-app

While the user has not finished, the server answers authorization_pending (keep polling at the given interval, and back off on slow_down); once they approve, the response contains the tokens. Device codes are short-lived and the user code should be hard to guess, since anyone who types it in can approve the request.

Refresh Token

A refresh token lets a client get a new access token without sending the user through login again. Access tokens are kept short-lived (minutes to an hour) so a leak is limited; the longer-lived refresh token stays on the server or in secure storage and is exchanged at the token endpoint:

POST /token
grant_type=refresh_token
&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=my-app

The server returns a new access token and often a new refresh token. For public clients, current guidance is to use refresh token rotation: each refresh token works once, and if an old one is replayed the server revokes the whole token family. Request the offline_access scope (or whatever your provider uses) if the app needs to keep working after the user has left.

  • Implicit returned the access token directly in the URL fragment of the redirect. Tokens ended up in browser history, referrer headers and logs, and there was no way to bind them to the client that asked. The OAuth 2.0 Security Best Current Practice (RFC 9700) advises against it, and OAuth 2.1 removes it. Single-page apps should use authorization code with PKCE instead.
  • Resource Owner Password Credentials has the app collect the user’s username and password and send them to the token endpoint. This teaches users to type their password into third-party apps, breaks multi-factor authentication and single sign-on, and gives the client far more power than it needs. OAuth 2.1 removes it as well. Migrate to authorization code with PKCE, or to the device flow when there is no browser.

Which Grant Type Should I Use?

Your appUse
Web app with a server backend, user signs inAuthorization Code (with PKCE)
Single-page app or mobile/native appAuthorization Code with PKCE
Backend service or script, no userClient Credentials
TV, console, CLI or IoT deviceDevice Code
Keeping a session alive without re-loginRefresh Token alongside one of the above
Old app still on Implicit or PasswordPlan a migration to the rows above

Is PKCE A Grant Type?

No, PKCE (Proof Key for Code Exchange) is not a grant type in OAuth 2.0.

Instead, PKCE is an extension to the OAuth 2.0 authorization code flow, designed to enhance security, particularly in scenarios where the client secret cannot be reliably stored, such as mobile or native applications.

In the OAuth 2.0 authorization code flow with PKCE, the core grant type remains the “Authorization Code” grant type.

PKCE introduces additional security measures during the authorization code exchange process by utilizing a dynamically generated secret (the code verifier) and a hash-based challenge (the code challenge). This mechanism helps mitigate certain security risks, such as authorization code interception attacks.

My avatar

Thanks for reading my blog post! Feel free to check out my other posts or contact me via the social links in the footer.


More Posts