Explainer · 5 min read

JWT vs OAuth 2.0 vs OpenID Connect

These three are often confused — but they solve different problems. JWT is a token format. OAuth 2.0 is an authorization framework. OpenID Connect is an authentication layer on top of OAuth 2.0. Here is how they fit together.

Overview

Side-by-side comparison

JWT
Token format
A compact, self-contained token format (RFC 7519). Encodes claims as a signed JSON object.
Handles: Representing identity and permissions in a verifiable, portable way.
OAuth 2.0
Authorization framework
An authorization framework (RFC 6749) that defines how applications request access to resources on behalf of a user.
Handles: Delegated authorization — "App X can read my Google Drive files."
OpenID Connect
Authentication layer
An identity layer built on top of OAuth 2.0 (OpenID Foundation spec). Adds an ID token and a /userinfo endpoint.
Handles: Authentication — verifying who the user is, not just what they can access.
Format

What is a JSON Web Token?

A JWT is a token format, not a protocol. It defines how to encode claims — user ID, roles, expiry — into a compact string that can be cryptographically signed and optionally encrypted. A JWT looks like xxxxx.yyyyy.zzzzz: a Base64URL-encoded header, payload, and signature joined by dots.

JWTs are self-contained — the server does not need to look up a session in a database to validate a JWT. It only needs the signing key. This makes them well-suited to stateless API authentication at scale.

JWTs are used as the token format within OAuth 2.0 and OpenID Connect flows — but you can also issue and validate JWTs entirely independently of those protocols.

Decode a JWT · How to create a JWT · How to validate a JWT

Authorization

What is OAuth 2.0?

OAuth 2.0 is an authorization framework(RFC 6749) that lets a user grant a third-party application limited access to their resources — without sharing their password. The classic example is "Sign in with Google" granting your app read access to a user's calendar.

OAuth 2.0 defines several grant types (flows) for different scenarios:

  • Authorization Code — for server-side apps and SPAs (with PKCE). The most secure flow.
  • Client Credentials — for machine-to-machine API authentication (no user involved).
  • Device Code — for devices with limited input (smart TVs, CLIs).

OAuth 2.0 produces an access token — often a JWT — that the client sends with API requests. It does not define what the token looks like, which is where JWT comes in.

Common misconception: OAuth 2.0 is not an authentication protocol. It tells you that a client is authorized to access a resource, not who the end user is. For that, you need OpenID Connect.

Authentication

What is OpenID Connect?

OpenID Connect (OIDC) is an identity layer built on top of OAuth 2.0. It adds a standardized ID token (always a JWT) and a /userinfo endpoint so the client can verify who the user is — not just what they are authorized to do.

Key additions over OAuth 2.0:

  • ID token — a JWT containing the user's identity (sub, email, name, etc.).
  • /userinfo endpoint — returns user profile claims when called with an access token.
  • Standardized claimssub, email, name, picture, and more defined in the spec.
  • Discovery document/.well-known/openid-configuration for auto-configuration.

When you implement "Sign in with Google", "Sign in with Apple", or any social login, you are using OpenID Connect. Auth providers like Auth0, Okta, and AWS Cognito implement the full OIDC spec.

In practice

How they fit together

A typical modern authentication flow combines all three:

  1. User authenticates via OpenID Connect — your app receives an ID token (JWT) proving who they are.
  2. Your auth server issues an access token (JWT) via OAuth 2.0 scoped to what the user can do.
  3. The client sends the access token as a Bearer header on API requests.
  4. Your API validates the JWT — checks signature, expiry, issuer, and audience — and serves the response.

In short: OIDC authenticates, OAuth 2.0 authorizes, and JWT is the format both use for tokens.

Alternative approaches

JWT vs session-based authentication

Before JWTs, most web apps used server-side sessions: the server stores session state in memory or a database, and the browser holds a session ID in a cookie. Both approaches are valid — the right choice depends on your architecture.

JWT (stateless)
  • No server-side session store needed
  • Scales horizontally without sticky sessions
  • Ideal for microservices and API authentication
  • Cannot be revoked before expiry (without a blocklist)
  • Payload is visible to anyone who holds the token
Sessions (stateful)
  • Instant revocation — delete the session
  • No sensitive data travels in the token
  • Simpler to implement for monolithic apps
  • Requires a shared session store at scale
  • Every request hits the session store

A common pattern is to use short-lived JWTs (5–15 min) for API authentication combined with a long-lived refresh token (stored in an HttpOnly cookie) to obtain new access tokens — giving you the scalability of JWTs with near-instant revocation via the refresh token.

Managed providers

Auth0, Okta, Cognito, and other providers

Services like Auth0, Okta, AWS Cognito, and Clerk implement OAuth 2.0 and OpenID Connect for you — handling token issuance, key rotation, social login, MFA, and user management. Your application only needs to:

  1. Redirect the user to the provider's authorization endpoint.
  2. Receive the authorization code callback.
  3. Exchange the code for tokens (access token + ID token — both JWTs).
  4. Validate the JWT on each API request using the provider's public keys (fetched from their /.well-known/jwks.json endpoint).

The JWTs issued by Auth0 are standard JWTs — you can paste them into the decoder on this page to inspect their claims. The key difference is that the signing key belongs to your Auth0 tenant, and you validate with their published public keys rather than your own secret.

→ See JWT Validation for how to verify tokens from any provider in Node.js, Python, C#, and Go.