Understanding OAuth2 & OpenID Connect (OIDC)
A clear guide to how OAuth2 and OIDC work together to provide modern authentication and secure delegated access.

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
The app redirects the user to the identity provider (IdP)
Example: Google, Auth0, Azure AD.The user logs in at the IdP
(Google checks the password or handles 2FA — your app never sees it.)After login, the IdP redirects back with an authorization code.
Your backend exchanges the code for two important tokens:
ID Token → proves the user’s identity
Access Token → optional, used to call APIs
Your app validates the ID Token (a signed JWT) and extracts identity details:
sub(user ID)emailprofilename
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:
The teacher is redirected from the 3rd-party app → Government IdP.
After login, the IdP asks the teacher to approve what information the 3rd-party app can access.
If approved, the IdP issues an authorization code.
The 3rd-party app exchanges the code for an access token.
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,departmentA standard way to retrieve more details via
/userinfoSecurity 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:
After the teacher authenticates, the IdP issues:
ID Token → proves identity
Access Token → grants permission to call APIs
The 3rd-party app validates the ID token signature using the IdP’s JWKS keys.
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
| Concept | In this scenario | What it does |
| IdP | Government identity system | Authenticates the teacher and issues tokens |
| OAuth2 | Authorization framework | Grants the 3rd-party app permission to access teacher-related data |
| OIDC | Authentication protocol | Confirms 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 Flowscope=openid→ enables OIDC (we want an ID token)state→ CSRF protectionnonce→ 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
kidUses 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
| Endpoint | Purpose | Who Uses It? |
| /authorize | User login + consent | Browser → IdP |
| /token | Code exchange → tokens | Backend → IdP |
| /jwks | Public keys for token validation | Backend |
| /userinfo | Fetch authenticated user profile | Backend or frontend |
Where Tokens Come From and How They’re Validated
Token issuance
During login:
User is redirected to
/authorize.After authentication, the IdP redirects back with an authorization code.
The app’s backend exchanges the code at
/token.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
/jwksiss(issuer) matches expected valueaud(audience) matches client IDexphas not expirednoncematches 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, pictureemail→ email addressread: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 identifieriss→ identity provider (issuer)aud→ client IDexp→ expiration timeiat→ issued atnonce→ replay protectionemail,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/userinfoenable 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.






