Intermediate

Grant types, client types, and client authentication

Choose the right OAuth grant, understand public and confidential clients, and compare client authentication methods.

A grant is the way a client obtains an access token. A client type describes whether the client can keep a secret. A client authentication method is how a confidential client proves its identity at the token endpoint. These three choices determine most of an OAuth integration’s security.

Grant types at a glance

Grantgrant_type valueUse it forStatus
Authorization code + PKCEauthorization_codeUsers signing in to web, mobile, desktop, and SPA clients.Recommended default.
Client credentialsclient_credentialsA service acting on its own behalf.Recommended for machine-to-machine.
Refresh tokenrefresh_tokenObtaining new access tokens without user interaction.Recommended, with rotation or sender constraint for public clients.
Device authorizationurn:ietf:params:oauth:grant-type:device_codeTVs, CLIs, and devices with limited input.Recommended where needed.
Token exchangeurn:ietf:params:oauth:grant-type:token-exchangeSwapping a token for another audience, scope, or actor.Specialized.
JWT bearerurn:ietf:params:oauth:grant-type:jwt-bearerExchanging a trusted signed assertion for a token.Specialized.
CIBAurn:openid:params:grant-type:cibaAuthenticating a user on a separate device, such as a call-center flow.Specialized (OpenID).
Implicitresponse_type=token—Not recommended (RFC 9700).
Resource owner passwordpassword—Must not be used (RFC 9700).

Authorization code with PKCE

1. Client creates code_verifier (random) and code_challenge = BASE64URL(SHA256(code_verifier))
2. Browser → GET /authorize?response_type=code&client_id=…&redirect_uri=…
                 &scope=…&state=…&code_challenge=…&code_challenge_method=S256
3. User authenticates and consents at the authorization server
4. Browser ← 302 redirect_uri?code=…&state=…&iss=…
5. Client  → POST /token  grant_type=authorization_code&code=…&redirect_uri=…&code_verifier=…
6. Client  ← { access_token, token_type, expires_in, refresh_token?, id_token? }

PKCE (RFC 7636) prevents a stolen authorization code from being redeemed by anyone who does not hold the code_verifier. Current guidance applies it to all clients, including confidential ones. Use S256; plain exists only for constrained legacy cases.

The state parameter protects the client against cross-site request forgery on its callback. The iss response parameter (RFC 9207) lets a client that talks to several authorization servers detect mix-up attacks.

Client credentials

The client authenticates and receives a token for itself. No user is involved, so there is no refresh token or consent. Scope the client narrowly and prefer strong client authentication. See giving a workload access to an API.

Refresh tokens

Refresh tokens allow long sessions with short-lived access tokens. They are powerful credentials:

  • Rotation: each use returns a new refresh token and invalidates the previous one. Reuse of an old token signals theft and should revoke the whole token family.
  • Sender constraint: bind refresh tokens to the client with DPoP or mutual TLS.
  • Lifetimes: set an absolute maximum and an idle timeout aligned with the session policy.

RFC 9700 requires public clients to use either rotation or sender-constrained refresh tokens.

Client types

TypeCan keep a secret?ExamplesConsequence
ConfidentialYesServer-side web app, backend service, BFF.Authenticates at the token endpoint.
PublicNoSingle-page app in the browser, mobile app, desktop app, CLI.Cannot authenticate; relies on PKCE, exact redirect URIs, and token binding.

A secret embedded in a mobile app or JavaScript bundle is not a secret: anyone can extract it. Register such clients as public.

Client authentication methods

The token_endpoint_auth_method client metadata names the method.

MethodHow it worksStrengthNotes
client_secret_basicShared secret in the HTTP Basic header.Low–mediumSimple; the secret is sent on every request and stored by both sides.
client_secret_postShared secret in the request body.Low–mediumSame as above; Basic is usually preferred.
client_secret_jwtJWT signed with HMAC using the shared secret.MediumSecret is not sent, but both sides still hold it.
private_key_jwtJWT signed with the client’s private key (RFC 7523).HighAuthorization server holds only the public key; supports key rotation via jwks_uri.
tls_client_authMutual TLS with a PKI-issued certificate (RFC 8705).HighNeeds certificate infrastructure; can also bind tokens.
self_signed_tls_client_authMutual TLS with a registered self-signed certificate.HighNo CA needed; certificate registered in client metadata.
noneNo authentication.—Public clients only.

For new confidential clients, prefer private_key_jwt or mutual TLS. High-security profiles such as FAPI 2.0 do not allow shared secrets.

Redirect URIs

Register redirect URIs exactly and compare them by exact string match. Wildcards and partial matches have caused many account-takeover vulnerabilities. Native apps follow RFC 8252; see native and mobile apps.

Choosing quickly

  • A person uses the application → authorization code + PKCE.
  • A backend calls an API for itself → client credentials with private_key_jwt or mTLS.
  • A device cannot show a browser → device authorization grant.
  • A service calls another service on behalf of a user → token exchange.

References

Knowledge is better when it is shared.Improve this page

Type to search the entire handbook.