OIDC (OpenID Connect)

Authentication Security Notes Jan 6, 2025 JAVASCRIPT

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

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

Standards & RFCs