Skip to main content

Command Palette

Search for a command to run...

Understanding OAuth2 & OpenID Connect (OIDC)

A clear guide to how OAuth2 and OIDC work together to provide modern authentication and secure delegated access.

Updated
11 min read
Understanding OAuth2 & OpenID Connect (OIDC)
N
Senior-level Fullstack Web Developer with 10+ years experience, including 2 years of Team Lead position. Specializing in responsive design and full-stack web development across the Vue.js and .NET ecosystems. Skilled in Azure/AWS cloud infrastructure, focused on DevOps techniques such as CI/CD. Experienced in system design, especially with software architecture patterns such as microservices, BFF (backend-for-frontend). Hands-on with Agile practices in team leading, and AI-assisted coding.

Series: Web Authentication Demystified — From Concepts to Real-World
ARC 1 — FOUNDATIONS OF USER AUTHENTICATION
Previous: Token Types Explained
Next: Authentication Flows

Modern authentication on the web is built on a pair of powerful, widely adopted standards: OAuth 2.0 and OpenID Connect (OIDC). These protocols make it possible for users to sign in with Google, Microsoft, GitHub, and countless identity providers — and they allow applications to securely access APIs, delegate permissions, and verify who a user is without ever handling a password.

This article breaks down the purpose of each protocol, what problems they solve, how they differ, and how tokens, scopes, and claims fit into the picture. By the end, you should have a solid mental model of how OAuth2 and OIDC actually work in practice.


OAuth2: Purpose, History, and Limitations

What OAuth2 Was Designed For

OAuth2 was created to solve a simple but fundamental problem:

How can one application access a user’s data on another service without knowing the user’s password?

Example:
You want to let a photo-editing app access images stored in your Google Photos account. How do you authorize that app securely?
Or in my case: A private sector firm wants to allow citizens to login as users into the firm’s application. How does the government authorize the app to access personal citizen identity?

OAuth2 is a framework for delegated authorization. It lets an application act on behalf of a user without ever knowing their password. Instead of sharing credentials, OAuth2 uses tokens granted through controlled flows. The app never learns the user’s password — only the access token, which represents a permission slip granted by the user.

Key idea:

OAuth2 is not an authentication protocol.
It never tries to answer: Who is the user?

It only answers:
Is this app allowed to do this thing?

What OAuth2 Actually Looks Like

User → App → Google Login Page → User Logs In → App Gets Authorization Code
         ↓
     App Exchanges Code → Gets Access Token → Calls API

Summary:

  • The user says: “Yes, this app can do this on my behalf.”

  • The identity provider (Google, Microsoft, GitHub) says: “Here’s a token proving you have permission.”

  • The app uses the token instead of a password.

A Brief History

Early OAuth 1.0 required complicated cryptographic signatures. OAuth2 (released in 2012) simplified this dramatically and exploded in popularity. Because of its flexibility, it quickly became the foundation for almost every modern API authorization flow.

But popularity came with misunderstandings — many teams tried to use OAuth2 for authentication, which wasn’t part of its design.

This misuse led directly to the creation of OpenID Connect (OIDC), which sits on top of OAuth2.

OAuth2 Limitations

OAuth2 has several gaps when used for authentication:

  • It provides access tokens, but they don’t prove user identity.

  • Tokens have no standard format (could be JWT or opaque).

  • No specification exists for user profile data.

  • No guidance on how clients should validate tokens.

  • No built-in protections for login-specific threats (replay, impersonation).

OAuth2 alone cannot log a user in safely.
That’s where OIDC comes in.


OpenID Connect (OIDC): What It Adds on Top of OAuth2

OIDC extends OAuth2 by adding a true authentication layer.

What OpenID Connect (OIDC) Actually Is

If OAuth2 tells an application what it can do, OpenID Connect (OIDC) tells the application who the user is. OIDC builds identity on top of OAuth2 by adding a standardized way to authenticate users and return ID tokens containing verified information about them.

In simple terms:

OIDC is “login with Google” done correctly.

It turns OAuth2’s authorization framework into a full authentication system.

What OIDC Looks Like

  1. The app redirects the user to the identity provider (IdP)
    Example: Google, Auth0, Azure AD.

  2. The user logs in at the IdP
    (Google checks the password or handles 2FA — your app never sees it.)

  3. After login, the IdP redirects back with an authorization code.

  4. Your backend exchanges the code for two important tokens:

    • ID Token → proves the user’s identity

    • Access Token → optional, used to call APIs

  5. Your app validates the ID Token (a signed JWT) and extracts identity details:

    • sub (user ID)

    • email

    • profile

    • name

Now your app knows who the user is without ever handling their password.

OIDC solves the missing pieces:

✔ Provides an ID token (a signed JWT that proves who the user is).
✔ Defines how clients request and validate identity information.
✔ Establishes a standard /userinfo endpoint.
✔ Adds nonce and other protections against replay attacks.
✔ Gives structure and requirements to token formats (JWT).

OIDC = OAuth2 + identity + safety

This distinction is important:

  • OAuth2 → authorization protocol

  • OIDC → authentication protocol built on OAuth2

OIDC finally gave developers a consistent, secure way to implement “Sign in with Google”-style authentication.


IdP vs OAuth2 vs OIDC (Clear Differences)

Here’s the separation many developers initially struggle with:

Identity Provider (IdP)

A service that authenticates users and issues tokens.
Examples:

  • Google Identity Platform

  • Azure AD

  • Auth0

  • Okta

  • Keycloak

An IdP implements OAuth2 and OIDC — it is not the protocol itself.

OAuth2

A protocol for authorization, allowing apps to obtain access tokens to call APIs.

OpenID Connect (OIDC)

A protocol for authentication, providing:

  • ID tokens

  • Standard claims

  • Token validation rules

  • UserInfo endpoint

A Clear Real-World Example (based on my experience)

Imagine a teacher working at a public-sector education institute. The government provides every teacher with a central digital identity managed by a national authentication platform. The teacher wants to log into a third-party educational web app used for lesson planning.

Here’s how IdP, OAuth2, and OIDC work together in this scenario — and how they differ.

1. IdP — The Identity Provider (Who authenticates the teacher?)

The government runs a national identity system — this is the IdP.

It is responsible for:

  • Verifying the teacher’s username/password

  • Performing MFA (e.g., SMS OTP or government-issued token)

  • Maintaining the authoritative identity record

  • Issuing tokens that other systems can trust

The IdP is the place where the teacher actually logs in.

In this example:

  • The government identity system = IdP

The teacher never enters their password into the 3rd-party app — only into the government IdP login page.

2. OAuth2 — Delegated Authorization (What is the teacher allowed to do?)

The 3rd-party app needs permission to access certain information about the teacher — for example:

  • Basic profile

  • Employment status

  • Role (e.g., “Teacher” vs “Principal”)

OAuth2 handles permission delegation.

OAuth2 does not identify the teacher.
Its job is simply to answer:

“Is this app allowed to access this data on the teacher’s behalf?”

What OAuth2 looks like in this scenario:

  1. The teacher is redirected from the 3rd-party app → Government IdP.

  2. After login, the IdP asks the teacher to approve what information the 3rd-party app can access.

  3. If approved, the IdP issues an authorization code.

  4. The 3rd-party app exchanges the code for an access token.

  5. The access token is used to call government APIs (e.g., "get profile").

OAuth2 solves the “permissions” and “API access” problem — not authentication.

3. OIDC — Authentication Layer (Who is the teacher?)

OIDC adds the missing identity features on top of OAuth2.

In this scenario, OIDC provides:

  • An ID token (a signed JWT proving the teacher’s identity)

  • Claims like name, email, teacherId, department

  • A standard way to retrieve more details via /userinfo

  • Security protections (nonce, state, JWT validation rules)

OIDC answers the question:

“Who is this teacher, and can I trust this identity?”

What OIDC looks like here:

  1. After the teacher authenticates, the IdP issues:

    • ID Token → proves identity

    • Access Token → grants permission to call APIs

  2. The 3rd-party app validates the ID token signature using the IdP’s JWKS keys.

  3. The app now knows:

    • This person is a verified teacher

    • Their unique government identity ID (sub)

    • Their name and email

    • Their role (if included in claims)

OIDC provides the identity proof.
OAuth2 provides the access rights.
The IdP provides the authentication service.

Putting It All Together

ConceptIn this scenarioWhat it does
IdPGovernment identity systemAuthenticates the teacher and issues tokens
OAuth2Authorization frameworkGrants the 3rd-party app permission to access teacher-related data
OIDCAuthentication protocolConfirms the teacher’s identity using signed ID Tokens

Standard Endpoints in OAuth2/OIDC

Every IdP exposes predictable URLs known as well-known endpoints. Below is what each endpoint looks like in practice, using a fictional government IdP as the example:

https://id.gov.example

1. Authorization Endpoint — /authorize

Where the browser gets redirected for login and consent.
Example Request

GET https://id.gov.example/oauth2/authorize?
  response_type=code&
  client_id=edu-app-123&
  redirect_uri=https://app.school.example/auth/callback&
  scope=openid%20profile%20email&
  state=af93jf02&
  nonce=8374hfhs

What’s happening:

  • response_type=code → using Authorization Code Flow

  • scope=openid → enables OIDC (we want an ID token)

  • state → CSRF protection

  • nonce → protects against replay attacks

After the user logs in at the IdP, the browser is redirected back to your app:

Example Redirect Back to App

https://app.school.example/auth/callback?code=abc123&state=af93jf02

2. Token Endpoint — /token

The backend exchanges authorization codes tokens.

Example Request (Backend → IdP)

POST https://id.gov.example/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=abc123&
redirect_uri=https://app.school.example/auth/callback&
client_id=edu-app-123&
client_secret=super-secret

Example Response

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_in": 3600,
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "def456refresh",
  "token_type": "Bearer"
}

What you receive:

  • access_token → to call protected APIs

  • id_token → proves the user's identity

  • refresh_token → used to get new tokens

  • token_type → usually "Bearer"

Your app now knows who the user is and what they can access.

3. JWKS Endpoint — /jwks

The JSON Web Key Set endpoint.
Provides the IdP’s public keys so clients can verify JWT signatures.

Example Request

GET https://id.gov.example/.well-known/jwks.json

Example Response

{
  "keys": [
    {
      "kid": "gov-key-1",
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "n": "0vx7agoebGcQSuuPiLJ...longkey...",
      "e": "AQAB"
    }
  ]
}

What your backend does with this

  • Finds the key with matching kid

  • Uses it to validate the signature of the ID token

  • Confirms who issued the token (iss)

  • Confirms who it was meant for (aud)

If everything checks out → the user is authenticated!

4. UserInfo Endpoint — /userinfo

Returns additional profile details (OIDC).

Example Request

GET https://id.gov.example/oidc/userinfo
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Example Response

{
  "sub": "teacher-98765",
  "name": "Nguyen Van A",
  "email": "nguyenvana@gov.example",
  "department": "Mathematics",
  "role": "Teacher"
}

What this endpoint is for:

  • Enriching the UI (show the teacher’s name/photo)

  • Mapping the external identity to your internal user account

  • Retrieving guaranteed, validated profile fields

Summary Table for Quick Reference

EndpointPurposeWho Uses It?
/authorizeUser login + consentBrowser → IdP
/tokenCode exchange → tokensBackend → IdP
/jwksPublic keys for token validationBackend
/userinfoFetch authenticated user profileBackend or frontend

Where Tokens Come From and How They’re Validated

Token issuance

During login:

  1. User is redirected to /authorize.

  2. After authentication, the IdP redirects back with an authorization code.

  3. The app’s backend exchanges the code at /token.

  4. The IdP returns:

    • ID token (who the user is)

    • Access token (what the app can access)

    • Refresh token (optional, long-lived)

Token validation

ID Token (JWT) validation

A client must verify:

  • Signature using keys from /jwks

  • iss (issuer) matches expected value

  • aud (audience) matches client ID

  • exp has not expired

  • nonce matches original request

If everything checks out → authentication is successful.

Access Token validation

Depending on format:

  • If JWT → validate signature and claims locally.

  • If opaque → call IdP’s introspection endpoint.

Resource servers (APIs) use access tokens to enforce scopes.


Role of Claims and Scopes

Scopes (OAuth2 and OIDC)

Scopes define what level of access the client is requesting.

Examples:

  • openid → enables OIDC (ID tokens required)

  • profile → name, gender, picture

  • email → email address

  • read:items, write:items → application-specific scopes

Scopes drive authorization.

Claims (JWT fields in ID tokens)

Claims describe:

  • identity

  • token metadata

  • permissions

Important claims:

  • sub → unique user identifier

  • iss → identity provider (issuer)

  • aud → client ID

  • exp → expiration time

  • iat → issued at

  • nonce → replay protection

  • email, name, picture (optional)

Claims drive authentication and token validation.


Summary

OAuth2 and OIDC are foundational to modern authentication and authorization:

  • OAuth2 delegates permissions and issues access tokens.

  • OIDC adds identity and issues ID tokens.

  • IdPs implement both protocols to authenticate users securely.

  • Standard endpoints such as /authorize, /token, /jwks, and /userinfo enable predictable flows.

  • Scopes control what’s allowed.

  • Claims provide verified information about the user and the token.

Together, OAuth2 and OIDC power nearly every SSO experience on the internet.

In the next article, we’ll zoom out from the protocols and explore authentication flows — Authorization Code, PKCE, and others — and learn when to choose which one.

Web Authentication Demystified — From Concepts to Real-World

Part 11 of 14

This series breaks down modern web authentication, from core concepts like OAuth, OIDC, and tokens to real implementation details. You’ll learn how the pieces fit together and see how a production-ready system is built and secured.

Up next

Token Types Explained: ID Tokens, Access Tokens, Refresh Tokens, Opaque Tokens & JWTs

A clear, practical guide to understanding modern authentication tokens and how they power OAuth2 and OpenID Connect.