A 36-minute working session on proving who a user is and deciding what they may do — from password hashing and sessions vs tokens, through OAuth 2.0 and OpenID Connect, to RBAC, the standards, and the tools that implement them.
Almost every security bug starts by blurring these two. They run in a fixed order: a system first establishes identity, and only then checks permission. Get the order — and the words — right, and the rest of this session clicks into place.
Identity first, permission second. A failed identity check returns 401 Unauthorized; a failed permission check returns 403 Forbidden.
Naming note the HTTP 401status is literally called "Unauthorized" but actually means unauthenticated — a historical quirk worth knowing.
A password, PIN, or recovery phrase. Cheap and universal — but reusable, phishable, and guessable. Never the only factor for anything that matters.
A phone running an authenticator app, a hardware security key, or a passkey on your device. A stolen password alone no longer gets the attacker in.
A fingerprint or face scan. Convenient and hard to share — but you can't change your face if the template leaks, so treat biometrics as a local unlock, not a server secret.
Multi-factor authentication (MFA) simply means requiring two of these from different categories — typically a password plus a phone or passkey. It is the single highest-leverage control you can add to a login.
A breach is not if but when. The only question is what an attacker finds in your database. Store passwords correctly and a full dump is nearly worthless to them. This is the most common — and most damaging — thing teams get wrong.
Password + unique salt → slow one-way hash → store the whole string. A good library does all three steps for you.
Winner of the Password Hashing Competition; tunable on memory and time, which resists GPU and ASIC cracking. The recommended first choice for new systems.
Decades of battle-testing and available everywhere. Perfectly fine today; note the ~72-byte input cap. A safe, boring choice.
Use when a compliance regime mandates them. PBKDF2 needs a high iteration count to stay slow — the whole point is to be deliberately slow.
verify), never a plain ==, to avoid timing leaks.HTTP is stateless — each request arrives as a stranger. So after a successful login we hand the browser something to present on every later request. There are two dominant designs, and the trade-off between them shapes your whole architecture.
The cookie is a meaningless ID; the truth lives in a store the server controls — so logging someone out is a single delete.
The token carries its own claims; the server only checks the signature — fast and stateless, but you can't un-issue it.
sub), when it expires (exp), and any roles or scopes.A JWT is header.payload.signature. Change one byte of the payload and the signature no longer matches.
Revocation is a delete in the store. Ideal for classic web apps, banking, anything where "kick this device out now" must be immediate.
No shared session store; any service can verify a request with just the public key. Great for APIs, mobile, and microservices.
A leaked JWT is valid until it expires. The fix: keep access tokens short-lived (minutes) and pair them with a stored, revocable refresh token.
Where you store it matters more than which you pick. Prefer an HttpOnly, Secure, SameSite cookie so JavaScript can't read it (defends against XSS token theft). Putting a JWT in localStorage is the classic mistake — any injected script can steal it.
OAuth and OIDC sound intimidating, but the core idea is simple: let a user grant one app limited access to their account on another, using a temporary key instead of a password. Once you see the four roles, the flow reads like a sentence.
The user who owns the account and grants access.
The application that wants access — e.g. a photo printing site.
Logs the user in and issues tokens — e.g. Google's login.
Holds the data and accepts the access token — e.g. Google Photos API.
The Authorization Code flow: the app never sees the password — only a short-lived code it swaps (with its secret) for tokens.
A scoped key the app sends to the resource server. It says what the bearer may do (scope: photos.read) — not who they are. Keep it short-lived.
A JWT describing who logged in — sub, email, name. This is what powers social login; your app reads it to create or match a local account.
Like a hotel: reception (auth server) checks your ID and gives you a room key card (access token) that opens only your room and the gym — not the safe, not other rooms — and expires at checkout. You never hand the cleaner your passport.
Authorization needs a model, not a pile of if checks scattered through your code. Two approaches dominate; most real systems start with the first and add a pinch of the second as rules get nuanced.
RBAC: users → roles → permissions. Change what an "editor" can do once, and every editor updates.
photos.read) — what the token may do. A claim is a statement about the user inside a token (role: admin, email_verified: true) — facts your authorization logic reads to make its decision.Authentication is a solved problem with sharp edges — rolling your own means re-discovering every vulnerability the industry already patched. The real decision is which standard to speak and which tool to lean on. Here are the leaders and where each fits.
Choose it when you need broad protocol support and enterprise features and would rather configure than build.
Choose it whenyou're building a modern web app and want login screens, MFA, and user management in an afternoon.
Choose it whenyou're shipping a mobile app or prototype and already live in Firebase/GCP.
Choose it when data residency, cost at scale, or no vendor lock-in outweigh the operational burden.
Choose it when requirements are simple and stable, or constraints rule out a hosted provider. Use a vetted library — never raw crypto.
Let's thread everything together: a user logs in, then tries to edit a post. Watch both gates do their job — identity, then permission — before the request is allowed through.
Login proves identity once and issues a token; every later request re-checks the token (AuthN) and the policy (AuthZ).
Both checks live on the server. The token answers who; the ownership/role check answers may they.
HttpOnly cookies.Five quick questions on authentication, hashing, tokens, OAuth/OIDC, and authorization — instant feedback, no sign-in.
Navigate with ← → or scroll · back to library