What You'll Learn
How modern stateless authentication works. We'll demystify the OAuth2 Authorization Code flow and break down the anatomy of a JSON Web Token (JWT).
The Problem with Session Cookies
Historically, when you logged in, the server created a session ID, stored it in memory or a database, and sent it to your browser via a Cookie. For every request, the server had to look up that session ID in the database to see who you were.
In modern microservice architectures, hitting a centralized database to verify a user on every single API request creates a massive bottleneck. The solution? Stateless Authentication with JWTs.
What is a JWT (JSON Web Token)?
A JWT is a string containing JSON data that is cryptographically signed by the server. Because it is signed, the server trusts the data inside it without needing to look it up in a database.
1. Header
Tells the server what algorithm was used to sign the token (e.g., HS256 or RS256).
2. Payload (Claims)
The actual data: User ID, role, and expiration time. Note: It is Base64 encoded, NOT encrypted! Do not put passwords here.
3. Signature
Created by hashing the Header + Payload using a secret key only the server knows. This guarantees the token hasn't been tampered with.
OAuth2 Authorization Code Flow
OAuth2 is an authorization framework. "Login with Google" is a classic example. Instead of giving Google your application password, OAuth2 allows Google to issue a token granting your app specific permissions.
- User Clicks Login: Your app redirects the user to the Authorization Server (e.g., Google/Auth0) with your Client ID and requested scopes.
- User Approves: The user logs into Google and clicks "Allow".
- Auth Code Redirect: Google redirects back to your application URL, passing a temporary
?code=xyz123in the URL. - Token Exchange (Backend): Your server takes that code and securely sends it to Google along with your Client Secret.
- Tokens Issued: Google verifies the secret and returns an Access Token (JWT) and a Refresh Token.
- API Access: Your app includes the Access Token in the
Authorization: Bearerheader when requesting data.
Access Tokens vs Refresh Tokens
Since JWTs are stateless, you cannot "revoke" them easily (unless you build a database blacklist, defeating the purpose of statelessness). Because of this, they are kept short-lived.
Access Token
- Sent with every API request.
- Very short lifespan (e.g., 15 minutes).
- If a hacker steals it, they only have access for 15 minutes.
Refresh Token
- Sent only to the Auth Server to get a new Access Token.
- Long lifespan (e.g., 30 days).
- Stored securely (HttpOnly Cookie). If compromised, the server can revoke it from the database.
Frontend Storage Security
Never store JWTs in LocalStorage! If your site has an XSS vulnerability, a hacker's JavaScript can read LocalStorage and steal the token. Instead, store tokens in an HttpOnly, Secure, SameSite=Strict cookie. JavaScript cannot read HttpOnly cookies, rendering them immune to XSS theft.