Skip to main content
OAuth 2.0

OAuth 2.0

Active

OAuth 2.0 is an authorization framework (RFC 6749) that enables third-party applications to obtain limited access to a user's resources without exposing credentials. Instead of sharing username/password, a user grants an application an access token with specific scopes. OAuth 2.0 defines four grant types for different client types and use cases. It is the foundation for API authorization across every major platform – Google, GitHub, Stripe, Salesforce.

OAuth 2.0RFC 6749AuthorizationBearerPKCEScopes2012
Grant Types

In one line

OAuth 2.0 (RFC 6749, 2012) is the industry standard for API authorization. Clients obtain access tokens from an authorization server; tokens are presented to resource servers. Four grant types: Authorization Code (web apps), Authorization Code + PKCE (mobile/SPA), Client Credentials (server-to-server), Device Flow (CLI/TV). Scopes limit what a token can access. Bearer tokens (RFC 6750) sent as Authorization: Bearer <token>. OAuth 2.1 draft consolidates best practices: PKCE required everywhere, implicit and password grants removed.

Quick Reference

FieldSizeDescription
Grant types4 active + 1 deprecatedAuthorization Code (web apps), Authorization Code + PKCE (public clients), Client Credentials (M2M), Device Flow (CLI/TV/IoT). Implicit (deprecated). Resource Owner Password (deprecated per OAuth 2.1).
Access tokenBearer tokenOpaque string or JWT. Presented in Authorization: Bearer <token> header. Short-lived (typically 1 hour). Resource servers validate without calling authorization server (if JWT) or via introspection (RFC 7662).
Refresh tokenLong-lived secretUsed to obtain new access tokens without user re-authentication. Stored securely server-side (never in browser). Rotate refresh tokens on each use (RFC 6749 §10.4). Not issued in Client Credentials flow.
ScopesSpace-separated stringsLimit access: read:users write:orders. Requested by client, granted by user, embedded in token. Principle of least privilege – request only the scopes you need.
Authorization codeShort-lived, one-timeExchanged for tokens in Authorization Code flow. Single use. Expires in ~10 minutes. PKCE binds the code to the code_verifier to prevent interception attacks.
PKCERFC 7636code_verifier: cryptographically random string (43–128 chars). code_challenge: BASE64URL(SHA256(code_verifier)). Required for all public clients (mobile, SPA). Required in OAuth 2.1 for all flows.
Token endpointPOST /oauth/tokenPOST with grant_type, code/credentials, client_id, client_secret (confidential clients). Returns access_token, token_type, expires_in, refresh_token, scope.
Bearer tokenRFC 6750Authorization: Bearer eyJhbGciOiJSUzI1NiIs... Tokens must be kept secret – any bearer can use them. Use HTTPS always. Never log tokens.

Key Characteristics

Delegated authorization

Users grant specific scopes to third-party apps without sharing credentials. The app gets a token limited to those scopes. Users can revoke tokens at any time.

Authorization not authentication

OAuth 2.0 is an authorization framework, not an authentication protocol. It tells you what a token can access, not who the user is. Use OpenID Connect (OIDC) on top of OAuth 2.0 for user identity.

Separation of concerns

Authorization Server (issues tokens) and Resource Server (validates tokens) are separate. Token validation can be done offline with JWTs or via introspection endpoint (RFC 7662).

PKCE is mandatory now

OAuth 2.1 mandates PKCE for all authorization code flows. Browser apps and mobile apps should always use PKCE even without OAuth 2.1. Prevents authorization code interception via redirect URI hijacking.

Message Format

Request
http
# Authorization Code + PKCE flow

# Step 1: Generate PKCE
code_verifier = base64url(crypto.randomBytes(32))  // 43–128 chars
code_challenge = base64url(sha256(code_verifier))

# Step 2: Redirect user to authorization server
GET https://auth.example.com/authorize?
  response_type=code
  &client_id=app_abc
  &redirect_uri=https://app.example.com/callback
  &scope=read:profile+write:orders
  &state=random-csrf-token
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256

# Step 3: Exchange code for tokens
POST https://auth.example.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=abc123
&redirect_uri=https://app.example.com/callback
&client_id=app_abc
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Response
http
# Token response
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "scope": "read:profile write:orders"
}

# Use access token
GET /api/v1/profile HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

# Refresh when expired
POST /oauth/token
grant_type=refresh_token
&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=app_abc

# Client Credentials (server-to-server, no user)
POST /oauth/token
grant_type=client_credentials
&client_id=svc_abc
&client_secret=secret_xyz
&scope=read:orders

Implementations

linuxsince Passport.js (Node.js), python-oauth2lib, golang.org/x/oauth2, Spring Security OAuth, Keycloak (IDP)available
macossince Same as Linux. Sign in with Apple uses OAuth 2.0 + OIDC.available
windowssince Microsoft.Identity.Client (MSAL), ASP.NET Core OAuth middleware, Azure AD.available
iossince AppAuth for iOS (Google), ASWebAuthenticationSession (iOS 12+). PKCE required per iOS guidelines.built-in
androidsince AppAuth for Android. Custom Tab for authorization. PKCE mandatory.built-in