Authentication and authorization get mixed up all the time, but they solve different problems. As a mid-level dev, you need not only to know the difference, but to choose between sessions and tokens, understand the structure of a JWT and explain where OAuth2 fits in. These topics come up in almost every back-end interview.
Authn vs Authz
Authentication (authn) answers "who are you?". Authorization (authz) answers "what are you allowed to do?". The analogy: authentication is showing your ID at a building's front desk; authorization is the badge that says which floors you can go up to. You have to prove who you are before finding out what you can access — authn first, then authz.
Session with a cookie
In the session model, the user logs in, the server creates a session and stores its state (in memory, a database or Redis). It returns a cookie with a session ID. On every request, the browser sends the cookie, and the server looks up the matching session:
login OK -> server stores session abc123 { userId: 7 }
-> Set-Cookie: session=abc123
request -> Cookie: session=abc123
-> server looks up abc123, knows it's user 7
The key point: the state lives on the server. This makes revoking access easy, but requires every server to share wherever the session is stored.
JWT tokens
With JWT (JSON Web Token), the server keeps no state. At login it generates a signed token containing the user's data, and the client sends it with every request (usually in the Authorization: Bearer ... header). The server only verifies the signature — it doesn't need to look anything up. That's why JWT is stateless, which fits REST APIs and scales well horizontally.
The structure of a JWT
A JWT has three parts separated by dots: header.payload.signature.
header -> { "alg": "HS256", "typ": "JWT" }
payload -> { "sub": 7, "role": "admin", "exp": 1735689600 }
signature -> HMAC(base64(header) + "." + base64(payload), SECRET)
Header and payload are just base64, not encryption — anyone can read them. The signature guarantees the content hasn't been tampered with, because only whoever has the secret can generate it. Hence the golden rule: never put secrets in the payload (passwords, sensitive data), since it's readable.
Session vs JWT
| Aspect | Session (cookie) | JWT (token) |
|---|---|---|
| State | On the server (stateful) | In the token (stateless) |
| Horizontal scaling | Needs a shared store | Natural, no store |
| Revocation | Easy (delete the session) | Hard (token is valid until it expires) |
| Size sent | Small (just the ID) | Larger (carries the data) |
OAuth2: delegated authorization
OAuth2 solves a different problem: letting an app access your data on another service without handing over your password. It's what happens with "sign in with Google". You're redirected to Google, authenticate there, and Google gives the app a token that authorizes only what you consented to. The app never sees your password. Important: OAuth2 is about delegated authorization, not about login — even though it's the foundation of social login flows.
Authentication proves who you are; authorization decides what you can do. A session keeps state on the server; a JWT carries state in the token. Confusing these pairs is the most common mistake in the field.
Security notes
Points that are always worth mentioning: set a short expiration on tokens (the exp claim) and use refresh tokens to renew them; always use HTTPS; mark cookies as HttpOnly and Secure; and remember that revoking a JWT before its time is a real problem — which is why long-lived tokens are risky.
Conclusion
Authn and authz are distinct, complementary layers. Sessions offer easy revocation; JWTs offer statelessness and scale. OAuth2 handles delegated access. Knowing when to use each one, and the security caveats of each choice, is exactly what's expected of a mid-level engineer.