DevToolsForYou
Auth & Security

How OAuth 2.0 Works

A practical guide to OAuth 2.0 — the authorization code flow, PKCE, tokens, scopes, and when to use each grant type.

2 min readUpdated Apr 11, 2026

What OAuth 2.0 is for

OAuth 2.0 is an authorization framework that lets a user grant a third-party application limited access to their account on another service — without sharing their password. For example, 'Sign in with Google' uses OAuth 2.0 to let you grant an app read access to your Google profile without giving the app your Google password.

The four roles

Resource Owner is the user. Client is your app (the one requesting access). Authorization Server is the service that issues tokens (e.g. Google, GitHub, your own auth server). Resource Server is the API that holds the protected data. The Authorization Server and Resource Server are often the same service.

The authorization code flow (most common)

This is the correct flow for web apps with a backend server. Never use the implicit flow — it has been deprecated.

text
1. User clicks 'Login with GitHub'

2. Your app redirects the user to:
   https://github.com/login/oauth/authorize
     ?client_id=YOUR_CLIENT_ID
     &redirect_uri=https://yourapp.com/callback
     &scope=read:user
     &state=RANDOM_CSRF_TOKEN
     &response_type=code

3. User logs in and approves access at GitHub

4. GitHub redirects back to your callback URL with:
   https://yourapp.com/callback?code=AUTH_CODE&state=RANDOM_CSRF_TOKEN

5. Your server POSTs to GitHub's token endpoint:
   POST https://github.com/login/oauth/access_token
   { client_id, client_secret, code, redirect_uri }

6. GitHub returns: { access_token, token_type, scope }

7. Your server uses access_token to call GitHub API on behalf of user

PKCE for SPAs and mobile apps

Single-page apps and mobile apps cannot safely store a client secret. PKCE (Proof Key for Code Exchange) replaces the client secret with a cryptographic challenge generated fresh for each request.

javascript
// 1. Generate a code_verifier (43–128 random URL-safe chars)
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));

// 2. Derive the code_challenge
const challenge = base64url(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier)));

// 3. Add to authorization URL:
//    &code_challenge=<challenge>
//    &code_challenge_method=S256

// 4. When exchanging the code for a token, send code_verifier
//    instead of client_secret

Access tokens and refresh tokens

An access token is a short-lived credential (typically 15 minutes to 1 hour) sent in the Authorization header of API calls. A refresh token is a long-lived credential stored securely server-side that can be exchanged for a new access token without the user re-authenticating. Never store either token in localStorage — use HttpOnly cookies or server-side sessions.

OAuth 2.0 vs OpenID Connect

OAuth 2.0 handles authorization (can this app access resource X?). OpenID Connect (OIDC) is a thin identity layer on top of OAuth 2.0 that handles authentication (who is this user?). When you need to know who the user is — not just what they can access — use OIDC. OIDC adds an id_token (a JWT) alongside the access token, containing the user's identity claims (sub, email, name).

Frequently asked questions

What is the difference between authentication and authorization?

Authentication is proving who you are (login). Authorization is determining what you are allowed to do. OAuth 2.0 is an authorization protocol. OpenID Connect adds authentication on top of it.

Should I build my own OAuth server?

Rarely. Auth is hard to get right and costly to maintain. Use a managed identity provider (Auth0, Clerk, Supabase Auth, Cognito) or an open-source solution (Keycloak, Authentik). Build your own only if you have specific requirements that off-the-shelf solutions cannot meet.

What is the state parameter for?

The state parameter is a random value your app generates and sends to the authorization server. When the user is redirected back, the state must match what you sent. This prevents CSRF attacks where an attacker tricks your callback into processing a code they control.

Related guidesAll guides →