Security

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.

A
Abhishek Patel9 min read

Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

OAuth 2.0 and OIDC: The Difference and When to Use Each
OAuth 2.0 and OIDC: The Difference and When to Use Each

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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

  1. Your app redirects the user to the authorization server's /authorize endpoint with the requested scopes.
  2. The user authenticates and consents to the requested permissions.
  3. The authorization server redirects back to your redirect_uri with an authorization code.
  4. Your backend sends the code, client ID, and client secret to the /token endpoint.
  5. The authorization server returns an access token (and optionally a refresh token).
  6. 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

FeatureOAuth 2.0OIDC
PurposeAuthorization (access to resources)Authentication (identity verification)
Token typeAccess token (opaque or JWT)ID token (always JWT) + access token
User identityNot standardizedStandard claims (sub, email, name, etc.)
DiscoveryNot defined/.well-known/openid-configuration
Userinfo endpointProvider-specificStandardized /userinfo
Session managementNot definedOptional 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:

  1. Your app generates a random code_verifier (43-128 characters).
  2. It computes code_challenge = BASE64URL(SHA256(code_verifier)).
  3. The code challenge is sent with the authorization request.
  4. When exchanging the code for tokens, the original code verifier is sent.
  5. 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:

ScenarioProtocolWhy
Users log in to your appOIDCYou need to know who the user is
Your app accesses a user's Google CalendarOAuth 2.0 + OIDCIdentity for login, authorization for API access
Microservice-to-microservice callsOAuth 2.0 (Client Credentials)No user involved, just service identity
Third-party apps access your APIOAuth 2.0Delegated access to resources
"Sign in with Google/GitHub" buttonOIDCFederated identity verification
API gateway token validationOAuth 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 openid scope 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:

ProviderFree TierPaid Starting AtBest For
Auth0 (Okta)25,000 MAU~$35/moDeveloper experience, extensive SDKs
AWS Cognito50,000 MAU$0.0055/MAUAWS-native apps, cost efficiency at scale
Google Identity Platform50,000 MAU$0.0055/MAUGCP-native, Firebase integration
Keycloak (self-hosted)Unlimited (OSS)Infra costs onlyFull control, on-prem requirements
Clerk10,000 MAU$25/moModern 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.

A

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

Enjoyed this article?

Get more like this in your inbox. No spam, unsubscribe anytime.

Comments

Loading comments...

Leave a comment

Stay in the loop

New articles delivered to your inbox. No spam.