Web & Backend
JWT and OAuth
A JWT (JSON Web Token) is a compact, signed piece of data — usually a user ID, an expiry, and a few other claims — that a server can verify without a database lookup. OAuth 2.0 is an authorization framework that lets a user grant a third-party application limited access to their data on another service, without ever handing that application their password. The two are often used together but solve different problems, and OpenID Connect is the layer built on top of OAuth that actually standardizes 'who is this user' rather than just 'what can this app do.'
Why it matters
- It's the mechanism behind most 'sign in with Google/GitHub' flows
- That familiar redirect-and-consent screen is OAuth (plus OpenID Connect) doing the work of proving identity without the app ever seeing the user's password.
- JWTs let a server verify a request with no session database lookup
- Because the token is self-contained and signed, an API server can check it's valid using just a key it already has, which matters for stateless, horizontally scaled backends.
- It's the standard way to delegate limited access between services
- An app can be granted access to just a user's calendar, or just their read-only profile, rather than needing their full account credentials.
What's actually inside a JWT
A JWT is three base64url-encoded segments separated by dots: a header, a payload of claims, and a signature. The signature proves the token wasn't tampered with since the server issued it, but the header and payload are only encoded, not encrypted — anyone holding the token can decode and read them, which is why sensitive data never belongs in a JWT's payload.
GET /api/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1XzQyIiwiZXhwIjoxNzU4MDAwMDAwfQ.4pfH1c...
// The middle segment, base64url-decoded, is just JSON:
{"sub": "u_42", "exp": 1758000000}The OAuth authorization code flow
In the most common flow, a user is redirected to the provider (say, GitHub), logs in there and approves the requested access, and GitHub redirects back to the application with a short-lived authorization code. The application's own server then exchanges that code, along with a secret only it knows, for an access token — the user's browser never sees or handles that token exchange, which keeps the secret off the client.
Authentication vs authorization, and where OpenID Connect fits
OAuth on its own answers 'what is this app allowed to do' — it was designed for delegated access, not for proving identity. OpenID Connect adds a standardized ID token (itself a JWT) on top of OAuth specifically to answer 'who is this user', which is what most 'social login' features actually rely on rather than raw OAuth alone.
Mistakes people make here
- Assuming a JWT is encrypted
- It's signed, not encrypted by default — the payload is just base64-encoded JSON that anyone with the token can read. Putting a password, a secret, or sensitive personal data in the payload exposes it to anyone who intercepts or is handed the token.
- Storing a JWT in localStorage
- It's readable by any JavaScript running on the page, so a cross-site scripting vulnerability anywhere on the site can exfiltrate every stored token. An httpOnly cookie, which JavaScript can't read at all, is the safer default for browser-based apps, at the cost of needing CSRF protection instead.
- Not validating the signature and expiry on every request
- A JWT is only as trustworthy as the verification step — a server that decodes the payload without checking the signature is trusting data an attacker could have forged from scratch.
- Confusing OAuth with a login system on its own
- OAuth alone proves an app was granted access to something, not who the user is — treating a bare OAuth access token as proof of identity, without OpenID Connect's ID token, is a common source of subtly broken 'social login' implementations.
Strengths and trade-offs
Where it is strong
- JWTs let an API verify a request statelessly, with no per-request session-store lookup.
- A JWT's claims travel with the token itself, which works well across multiple services that all trust the same signing key.
- OAuth lets a user grant limited, specific access without ever sharing their password with the requesting app.
- Both are industry standards with mature libraries in essentially every language, so teams rarely have to implement the cryptography themselves.
The trade-offs
- A JWT can't be revoked before it expires without extra infrastructure, such as a blocklist — the usual mitigation is keeping tokens short-lived and pairing them with a separate refresh token.
- A JWT's payload is world-readable to anyone holding the token, since signing is not the same as encryption.
- OAuth's flow has several moving parts — redirect URIs, state parameters, PKCE — and a misconfigured one is a genuine, recurring source of real vulnerabilities.
- Every extra claim in a JWT adds bytes to every single request that carries it, unlike a session ID that stays small regardless of how much server-side state it references.
Who needs this
Essential for anyone building login, 'sign in with X', or authenticated API access between services; the details of token expiry and storage matter even in straightforward apps.
Questions about jwt and oauth
- Is a JWT encrypted?
- No, not by default — it's signed, which proves it hasn't been tampered with, but the payload itself is just encoded, not hidden. A separate, less common format called JWE handles actual encryption if that's needed.
- Is OAuth the same as OpenID Connect?
- No. OAuth 2.0 is about delegated authorization — granting an app limited access to do something. OpenID Connect is built on top of OAuth specifically to standardize authentication — proving who the user is — via an additional ID token.
- How long should a JWT last before it expires?
- There's no universal number; it's a trade-off between security (a stolen token is only useful until it expires) and convenience (a very short-lived token means frequent re-authentication). Most systems use a short-lived access token paired with a longer-lived refresh token to balance the two.
- Is it safe to store a JWT in localStorage?
- It works, but it's exposed to any script that runs on the page, including one injected through a cross-site scripting bug. An httpOnly cookie is generally the safer default for browser-based web apps, though it brings its own need for CSRF protection.