OAuth 2.0 and OIDC: The Difference and When to Use Each
OAuth 2.0 handles authorization while OIDC handles authentication. Learn the grant types, token differences, PKCE, and when to use each protocol.
Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

Two Protocols, One Login Button
You've clicked "Sign in with Google" hundreds of times. Behind that button, two protocols are doing very different jobs: OAuth 2.0 handles authorization -- what an app is allowed to do on your behalf -- while OpenID Connect (OIDC) handles authentication -- proving who you are. Confusing the two is the single most common mistake teams make when building identity systems, and it leads to security holes that are painful to fix after launch.
OAuth 2.0 has been the industry standard for delegated authorization since 2012. OIDC was layered on top of it in 2014 to solve the authentication problem OAuth deliberately left out of scope. If you're building any application that lets users log in through a third party, you need to understand both -- where they overlap, where they diverge, and when you need one, the other, or both.
What Is OAuth 2.0?
Definition: OAuth 2.0 is an authorization framework that allows a third-party application to obtain limited access to a user's resources on another service, without exposing the user's credentials. It issues access tokens that define what the application can do, not who the user is.
OAuth 2.0 replaced OAuth 1.0's complicated signature scheme with bearer tokens over TLS. The core idea is simple: instead of giving an app your password, you grant it a token with specific permissions (scopes). The token expires, can be revoked, and limits damage if compromised.
OAuth 2.0 Grant Types
OAuth 2.0 defines several flows for obtaining tokens. Here's what matters in 2026:
- Authorization Code Grant -- The standard for server-side web apps. The user authenticates with the authorization server, which redirects back with a short-lived code. Your backend exchanges that code for tokens. The user never sees the tokens.
- Authorization Code + PKCE -- Required for single-page apps and mobile apps. PKCE (Proof Key for Code Exchange) adds a code verifier/challenge pair that prevents authorization code interception attacks. This replaced the Implicit flow.
- Client Credentials -- Machine-to-machine communication with no user involved. Your service authenticates directly with the authorization server using a client ID and secret. Used for backend microservice calls.
- Device Authorization Grant -- For devices without browsers (smart TVs, CLI tools). The device displays a code; the user enters it on a separate device with a browser.
Watch out: The Implicit Grant is deprecated. It returned tokens directly in the URL fragment, which exposed them to browser history and referrer headers. If you're still using it, migrate to Authorization Code + PKCE immediately.
Authorization Code Flow Step by Step
- Your app redirects the user to the authorization server's
/authorizeendpoint with the requested scopes. - The user authenticates and consents to the requested permissions.
- The authorization server redirects back to your
redirect_uriwith an authorization code. - Your backend sends the code, client ID, and client secret to the
/tokenendpoint. - The authorization server returns an access token (and optionally a refresh token).
- Your app uses the access token to call the resource server's API.
GET /authorize?
response_type=code
&client_id=your-client-id
&redirect_uri=https://yourapp.com/callback
&scope=read:profile
&state=random-csrf-token
&code_challenge=BASE64URL(SHA256(code_verifier))
&code_challenge_method=S256
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTH_CODE_FROM_CALLBACK
&redirect_uri=https://yourapp.com/callback
&client_id=your-client-id
&client_secret=your-client-secret
&code_verifier=ORIGINAL_CODE_VERIFIER
What Is OpenID Connect (OIDC)?
Definition: OpenID Connect (OIDC) is an identity layer built on top of OAuth 2.0. It adds a standardized way to verify user identity by introducing ID tokens (JWTs containing user claims), a userinfo endpoint, and a discovery mechanism. OIDC answers "who is this user?" while OAuth answers "what can this app do?"
Before OIDC, developers abused OAuth 2.0 for authentication by calling a provider-specific API (like Facebook's /me endpoint) with an access token. Every provider did it differently. OIDC standardized this by defining exactly what an identity response looks like.
What OIDC Adds to OAuth 2.0
| Feature | OAuth 2.0 | OIDC |
|---|---|---|
| Purpose | Authorization (access to resources) | Authentication (identity verification) |
| Token type | Access token (opaque or JWT) | ID token (always JWT) + access token |
| User identity | Not standardized | Standard claims (sub, email, name, etc.) |
| Discovery | Not defined | /.well-known/openid-configuration |
| Userinfo endpoint | Provider-specific | Standardized /userinfo |
| Session management | Not defined | Optional spec for session tracking |
The ID Token
The ID token is a JWT signed by the authorization server. It contains standard claims:
{
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"aud": "your-client-id",
"exp": 1712345678,
"iat": 1712342078,
"nonce": "random-nonce-from-request",
"email": "user@example.com",
"email_verified": true,
"name": "Jane Doe",
"picture": "https://example.com/photo.jpg"
}
Your app validates the ID token by checking the signature against the provider's public keys (published at the JWKS URI), verifying the iss, aud, and exp claims, and confirming the nonce matches what you sent. If all checks pass, you know who the user is.
Standard Scopes and Claims
OIDC defines standard scopes that map to sets of claims:
openid-- Required. Signals this is an OIDC request and triggers ID token issuance.profile-- Name, family name, picture, locale, updated_at.email-- Email address and whether it's verified.address-- Postal address.phone-- Phone number and whether it's verified.
PKCE: Why It Matters for Every Client
PKCE (pronounced "pixie") was originally designed for public clients that can't safely store a client secret -- mobile apps, SPAs, CLI tools. But as of OAuth 2.1, PKCE is recommended for all clients, including confidential ones.
Here's how it works:
- Your app generates a random
code_verifier(43-128 characters). - It computes
code_challenge = BASE64URL(SHA256(code_verifier)). - The code challenge is sent with the authorization request.
- When exchanging the code for tokens, the original code verifier is sent.
- The authorization server hashes the verifier and compares it to the stored challenge.
This prevents an attacker who intercepts the authorization code from exchanging it for tokens -- they don't have the code verifier.
When to Use OAuth, OIDC, or Both
This is the question that trips up most teams. Here's a clear decision framework:
| Scenario | Protocol | Why |
|---|---|---|
| Users log in to your app | OIDC | You need to know who the user is |
| Your app accesses a user's Google Calendar | OAuth 2.0 + OIDC | Identity for login, authorization for API access |
| Microservice-to-microservice calls | OAuth 2.0 (Client Credentials) | No user involved, just service identity |
| Third-party apps access your API | OAuth 2.0 | Delegated access to resources |
| "Sign in with Google/GitHub" button | OIDC | Federated identity verification |
| API gateway token validation | OAuth 2.0 (token introspection or JWT) | Verifying access, not identity |
Pro tip: If you're adding "Sign in with X" to your app, you always want OIDC. Pure OAuth 2.0 tells you the user granted access -- it doesn't reliably tell you who they are. The
openidscope is what triggers the identity layer.
Costs and Provider Comparison
If you're not building your own authorization server, you'll use a managed identity provider. Here's how the major options compare in 2026:
| Provider | Free Tier | Paid Starting At | Best For |
|---|---|---|---|
| Auth0 (Okta) | 25,000 MAU | ~$35/mo | Developer experience, extensive SDKs |
| AWS Cognito | 50,000 MAU | $0.0055/MAU | AWS-native apps, cost efficiency at scale |
| Google Identity Platform | 50,000 MAU | $0.0055/MAU | GCP-native, Firebase integration |
| Keycloak (self-hosted) | Unlimited (OSS) | Infra costs only | Full control, on-prem requirements |
| Clerk | 10,000 MAU | $25/mo | Modern DX, pre-built UI components |
Common Mistakes and How to Avoid Them
Using Access Tokens for Authentication
An access token tells a resource server what the bearer is allowed to do. It doesn't reliably identify the user to your app. Access tokens can be issued to any client, and some providers issue opaque tokens with no user info. Always use the ID token for authentication.
Skipping State Parameter Validation
The state parameter prevents CSRF attacks on the callback endpoint. Generate a random value, store it in the session, and verify it when the callback arrives. Without it, an attacker can craft a URL that logs a victim into the attacker's account.
Not Validating ID Token Claims
You must verify the iss (issuer), aud (audience), exp (expiration), and nonce claims on every ID token. Libraries handle this, but misconfigured audience validation is a frequent source of token confusion attacks.
Frequently Asked Questions
Is OAuth 2.0 an authentication protocol?
No. OAuth 2.0 is an authorization framework. It grants access to resources but doesn't define a standard way to verify user identity. OIDC was built on top of OAuth 2.0 specifically to add authentication. Using OAuth alone for login is possible but requires provider-specific workarounds that OIDC standardizes.
What is the difference between an access token and an ID token?
An access token authorizes API calls to a resource server -- it defines what you can do. An ID token is a JWT that identifies the user -- it defines who you are. Access tokens go to APIs. ID tokens stay with your application. Never send an ID token to an API as a bearer token.
Is the Implicit Grant still safe to use?
No. The Implicit Grant is deprecated in OAuth 2.1. It exposed tokens in browser URLs, making them vulnerable to leakage through browser history, referrer headers, and open redirector attacks. All browser-based apps should use Authorization Code with PKCE instead.
Do I need OIDC if I'm only building machine-to-machine APIs?
No. Machine-to-machine communication uses the OAuth 2.0 Client Credentials grant. There's no user to authenticate, so OIDC adds no value. Your services authenticate with client IDs and secrets (or mutual TLS), and the resulting access tokens authorize API calls.
What is PKCE and when should I use it?
PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks by binding the code to the client that requested it. OAuth 2.1 recommends PKCE for all clients -- not just public ones. It adds minimal complexity and closes a real attack vector, so there's no reason to skip it.
Can I use OAuth 2.0 with multiple identity providers simultaneously?
Yes. Your app can support Google, GitHub, and Microsoft as identity providers at the same time. Each provider issues its own tokens. Your app validates each against the correct issuer's keys and maps the sub claim to a local user account. OIDC discovery makes this straightforward to configure.
How do refresh tokens work in OAuth 2.0?
Refresh tokens are long-lived tokens used to obtain new access tokens without user interaction. When an access token expires, your app sends the refresh token to the token endpoint. The server issues a new access token (and optionally rotates the refresh token). Store refresh tokens securely -- they're equivalent to persistent credentials.
Putting It Together
OAuth 2.0 and OIDC aren't competing protocols -- they're complementary layers. OAuth handles authorization, OIDC handles authentication, and most real-world applications need both. Start with OIDC for user login, add OAuth scopes when you need to access third-party APIs, and use Client Credentials for service-to-service calls. Pick a grant type based on your client type, always use PKCE, validate every token properly, and you'll avoid the security pitfalls that catch most teams.
Written by
Abhishek Patel
Infrastructure engineer with 10+ years building production systems on AWS, GCP, and bare metal. Writes practical guides on cloud architecture, containers, networking, and Linux for developers who want to understand how things actually work under the hood.
Related Articles
Network Firewalls vs WAFs: Understanding Your Defense Layers
Network firewalls filter by IP and port at Layer 3/4. WAFs inspect HTTP content at Layer 7. Learn when you need each and how to configure them together.
10 min read
SecurityCertificate Management at Scale: Let's Encrypt, ACME, and cert-manager
Automate TLS certificates with Let's Encrypt, ACME protocol, and cert-manager in Kubernetes. Covers HTTP-01, DNS-01, wildcards, private CAs, and expiry monitoring.
9 min read
SecuritySSRF Attacks: What They Are and Why Cloud Environments Make Them Dangerous
SSRF lets attackers reach internal services through your server. Learn how cloud metadata endpoints amplify the risk and how to defend against SSRF.
9 min read
Enjoyed this article?
Get more like this in your inbox. No spam, unsubscribe anytime.