OAuth 2.0 vs OpenID Connect — What is Actually Different?
OAuth 2.0 answers "can this app access your data?" OpenID Connect answers "who are you?" OIDC is an identity layer built on top of OAuth — it adds a standard way to get user identity information alongside access tokens.
OAuth 2.0 — authorization only
OAuth gives your app an access token to call an API on the user's behalf. The token proves the user authorized your app to access specific resources (scopes). OAuth does not tell your app anything about who the user is — just that they granted permission.
# After OAuth, you have an access token # You can call the API: GET /api/data HTTP/1.1 Authorization: Bearer eyJhbGc... # But you do not know WHO authorized this — OAuth does not define that
OpenID Connect — authentication on top
OIDC adds an ID token (a JWT) to the OAuth response. This token contains standard claims about the user's identity — sub (user ID), name, email, picture. OIDC also defines a standard /userinfo endpoint to fetch additional claims.
# OIDC adds id_token to the token response
{
"access_token": "eyJhbGc...",
"id_token": "eyJhbGc...", // JWT with user identity claims
"expires_in": 3600,
"token_type": "Bearer"
}
# Decoded id_token contains:
{
"sub": "user123", // unique user ID
"name": "Jane Smith",
"email": "jane@example.com",
"iss": "https://accounts.google.com",
"aud": "your-client-id",
"exp": 1234567890
}
When to use which
| Scenario | Use |
|---|---|
| Machine-to-machine API access | OAuth (client credentials flow) |
| Let users log in to your app | OIDC (authorization code + PKCE) |
| Access Google Drive on user's behalf | OAuth with Google's scopes |
| Sign in with Google | OIDC — you get the user's identity |
| Third-party API integration | OAuth — just need the access token |
The scope that signals OIDC
Include openid in your scope to activate OIDC and receive an ID token. Without it, you get plain OAuth — access token only, no identity information.
scope=openid profile email // OIDC — returns id_token + access_token scope=read:data // plain OAuth — returns access_token onlyDebug your OAuth errors → OAuthFixer