Every time you click "Login with Google" or "Sign in with GitHub," you're using OAuth 2.0. It's the industry standard protocol for authorization — and with OpenID Connect (OIDC) layered on top, it handles authentication too. Understanding OAuth is essential for any web developer building apps with third-party login or API integrations.
Authentication vs Authorization
- Authentication (AuthN): "Who are you?" — Verifying identity. This is what OpenID Connect handles.
- Authorization (AuthZ): "What can you do?" — Granting permissions. This is what OAuth 2.0 handles.
OAuth 2.0 was designed for authorization — allowing a third-party app to access your Google Drive files without giving it your Google password. OpenID Connect adds an authentication layer on top, providing a standardized way to get user identity information.
The Key Players
- Resource Owner: The user who owns the data (you)
- Client: The application requesting access (your app)
- Authorization Server: The service that authenticates the user and issues tokens (Google, GitHub, Auth0)
- Resource Server: The API that holds the protected data (Google Drive API, GitHub API)
Authorization Code Flow (with PKCE)
This is the recommended flow for web applications and single-page apps. PKCE (Proof Key for Code Exchange) adds security by preventing authorization code interception attacks.
1. User clicks "Login with Google" on your app
2. Your app redirects the user to Google's authorization endpoint:
GET https://accounts.google.com/o/oauth2/v2/auth?
response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&scope=openid email profile
&state=random_csrf_token
&code_challenge=SHA256_HASH
&code_challenge_method=S256
3. User logs in to Google and grants permission
4. Google redirects back to your app with an authorization code:
GET https://yourapp.com/callback?code=AUTH_CODE&state=random_csrf_token
5. Your server exchanges the code for tokens:
POST https://oauth2.googleapis.com/token
Body: {
code: AUTH_CODE,
client_id: YOUR_CLIENT_ID,
client_secret: YOUR_CLIENT_SECRET,
redirect_uri: https://yourapp.com/callback,
grant_type: authorization_code,
code_verifier: ORIGINAL_RANDOM_STRING
}
6. Google returns:
{
"access_token": "ya29.a0...",
"id_token": "eyJhbGci...", // OpenID Connect
"refresh_token": "1//0e...",
"expires_in": 3600,
"token_type": "Bearer"
}
Understanding Tokens
- Access Token: Short-lived (typically 1 hour). Used to call APIs on behalf of the user. Include it in the
Authorization: Bearer <token>header. - Refresh Token: Long-lived. Used to get new access tokens without re-authenticating the user. Store securely (server-side only, never in localStorage).
- ID Token: A JWT containing user identity info (email, name, picture). This is the OpenID Connect addition to OAuth.
Scopes
Scopes define what permissions your app requests. The user sees these during the consent screen.
// OpenID Connect scopes openid // Required for OIDC email // User's email address profile // Name, picture, locale // Google-specific scopes https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/calendar // GitHub scopes read:user // Read user profile repo // Full access to repositories read:org // Read org membership
Security Best Practices
- Always use PKCE — even for server-side apps. It's required for public clients (SPAs, mobile apps).
- Validate the
stateparameter to prevent CSRF attacks. - Never store tokens in localStorage. Use HTTP-only, secure, SameSite cookies.
- Validate ID tokens — check the issuer, audience, expiration, and signature.
- Request minimal scopes — only ask for what you actually need.
- Use short-lived access tokens with refresh token rotation.
When to Use What
- Authorization Code + PKCE: Web apps, SPAs, mobile apps (the default choice)
- Client Credentials: Server-to-server communication (no user involved)
- Device Code: Smart TVs, CLIs, IoT devices (limited input capability)
- ⚠️ Implicit Flow: Deprecated. Don't use it for new apps.
Try Our Free Developer Tools
Decode and inspect JWTs and Base64-encoded tokens.