Definition
Here’s the problem OAuth 2.0 doesn’t solve: it tells an app what you’re allowed to do, but not who you are. If you give a website permission to read your Google Drive files, OAuth handles that - but the website still doesn’t know your name, email, or anything about you. They’d have to make extra API calls to get that, and every provider does it differently. OpenID Connect (OIDC) fixes this by adding a standardized identity layer on top of OAuth.
When you click “Sign in with Google,” you’re using OIDC, not just OAuth. The magic is in the ID token - a special JWT that contains verified information about you: your unique identifier, email, name, profile picture, and when you authenticated. Unlike access tokens (which are for accessing APIs), ID tokens are specifically for proving identity. The app doesn’t need to call Google’s API to learn who you are; your identity information arrives along with the tokens.
OIDC also standardizes discovery. Instead of every provider having different endpoints and formats, OIDC providers publish a .well-known/openid-configuration document that tells your app exactly where to find everything. “Here’s my authorization endpoint, here’s my token endpoint, here’s where to get my signing keys.” This means your code can work with Google, Microsoft, Okta, or any OIDC provider without changes. It’s why “Sign in with…” buttons are everywhere - OIDC made identity interoperable in a way that never existed before.
Example
OIDC is the invisible standard powering identity across the modern web:
Social Login Buttons: When you click “Sign in with Google,” “Log in with Microsoft,” or “Continue with Apple,” you’re using OIDC. The app doesn’t store your password - it trusts Google/Microsoft/Apple to verify your identity and provide standardized claims in an ID token. This is why you see these buttons on millions of sites; they all speak the same OIDC language.
Enterprise Single Sign-On: When you log into your company laptop and suddenly have access to Slack, Salesforce, and hundreds of internal apps without logging in again, that’s OIDC federating your identity from your corporate directory (Azure AD, Okta) to every application. IT administrators love this because there’s one place to disable access when someone leaves.
Mobile App Authentication: When a banking app lets you “sign in with your bank ID,” it’s using OIDC to get verified identity information. The app receives an ID token proving you’re the account holder, including which authentication methods you used (password, fingerprint, face recognition) - important for security-sensitive operations.
Developer Platforms: When you sign into GitHub with your corporate account, or into AWS with your organization’s identity provider, OIDC is bridging those worlds. Your corporate identity works across different platforms without each one needing to store your credentials.
Consumer Apps: Apps like Spotify using “Log in with Facebook” benefit from OIDC’s standardized claims. They immediately know your name, email, and profile picture - enough to personalize your experience from the first second, without asking you to fill out a registration form.
Analogy
The Universal Passport System: Imagine if every country had its own passport format - some with photos, some without, some with fingerprints, some with just a name. International travel would be chaos. OIDC is like the international standard for passports: every “country” (identity provider) issues credentials in the same format, and every “border agent” (application) knows exactly how to read them. You present one passport everywhere.
The Hotel Key Card System: When you check into a hotel, you prove your identity once at the front desk (authentication), and they give you a key card (ID token). That card contains encoded information about you - your room number, checkout date, gym access. You don’t re-prove your identity at every door; you just present the card. OIDC works the same way: authenticate once with Google, get an ID token, and use it to prove who you are to multiple applications.
The Employee Badge: Your company badge has your photo, name, and department - that’s like an ID token. It proves who you are to security guards (relying parties). The badge was issued by HR (the identity provider) who verified your identity when you were hired. You don’t need HR to walk with you everywhere; the badge carries your verified identity.
The Notarized Document: When you get a document notarized, a trusted third party (notary/identity provider) stamps it to verify it’s really from you. Anyone receiving that document can trust its authenticity without calling you directly. OIDC’s ID tokens work similarly - they’re cryptographically signed by the identity provider, so apps can trust the claims without asking the provider “is this really user X?”
Diagram
sequenceDiagram
participant User
participant App as Client App
participant Auth as OIDC Provider
participant UserInfo as UserInfo Endpoint
User->>App: 1. Click "Sign in with Provider"
App->>Auth: 2. Authorization request
(scope: openid email profile)
Auth->>User: 3. Login + consent
User->>Auth: 4. Approve
Auth->>App: 5. Authorization code
App->>Auth: 6. Exchange code for tokens
Auth->>App: 7. Response includes:
- access_token
- refresh_token
- id_token (JWT)
Note over App: ID Token contains identity claims
rect rgb(200, 230, 255)
App->>App: 8. Validate & decode ID token
Note over App: Claims in ID token:
sub: "user123"
email: "[email protected]"
name: "John Doe"
picture: "https://..."
iat, exp, iss, aud, nonce
end
opt Additional user info needed
App->>UserInfo: 9. GET /userinfo
(Bearer access_token)
UserInfo->>App: 10. Extended user claims
end
Code Example
// OIDC Authentication Flow
const { Issuer, generators } = require('openid-client');
// Discover OIDC provider configuration
const issuer = await Issuer.discover('https://oauth.provider.com');
const client = new issuer.Client({
client_id: 'your_client_id',
client_secret: 'your_client_secret',
redirect_uris: ['https://yourapp.com/callback'],
response_types: ['code']
});
// Generate PKCE and nonce
const code_verifier = generators.codeVerifier();
const code_challenge = generators.codeChallenge(code_verifier);
const nonce = generators.nonce();
// Build authorization URL
const authUrl = client.authorizationUrl({
scope: 'openid email profile',
code_challenge,
code_challenge_method: 'S256',
nonce
});
// Handle callback
const params = client.callbackParams(req);
const tokenSet = await client.callback(
'https://yourapp.com/callback',
params,
{ code_verifier, nonce }
);
// TokenSet contains both access_token and id_token
const { id_token, access_token, refresh_token } = tokenSet;
// Verify and decode ID token (happens automatically above)
const claims = tokenSet.claims();
console.log('User identity:', {
sub: claims.sub, // User ID
email: claims.email,
name: claims.name,
picture: claims.picture
});
// Optionally fetch additional user info
const userinfo = await client.userinfo(access_token);
Security Notes
CRITICAL: OpenID Connect adds authentication layer on OAuth 2.0. Enables user identity verification.
OIDC Components:
- ID Token: Proves user identity (JWT)
- Access Token: Authorizes API access
- UserInfo endpoint: Get additional user info
- Claims: User attributes (name, email, picture, etc.)
Flows:
- Authorization Code: Standard flow for web apps
- Hybrid: Combines implicit and authorization code
- Implicit: Deprecated, use with PKCE instead
- Client Credentials: Machine-to-machine, no user
ID Token Security:
- Verify signature: Always verify ID token signature
- Validate claims: Verify iss, aud, exp
- Use for identification: ID tokens for user identification
- Don’t authorize: Never use ID token for API authorization
Best Practices:
- Use Authorization Code: Standard flow for apps
- Use PKCE: Required for public clients
- Validate nonce: Include nonce for CSRF protection
- Secure storage: Store tokens securely