These two get mixed up constantly, and interviewers love catching us on it. In simple language — authentication answers “who are you?” and authorization answers “what are you allowed to do?”
Same prefix, totally different jobs. Authn always comes first: we can’t decide what someone’s allowed to do until we know who they are.
Authentication — proving who you are
Authentication (authn) is the process of verifying identity. We hand over some proof — a password, a token, a fingerprint — and the server checks it’s really us.
Think of it like showing your passport at the airport. The officer confirms the face matches the photo. That’s it — no decision yet about where you’re allowed to fly.
Common ways we authenticate:
- Something we know — password, PIN
- Something we have — a phone for OTP, a hardware key
- Something we are — fingerprint, face scan
Combine two of those and it’s MFA (multi-factor authentication).
Authorization — deciding what you can do
Authorization (authz) happens after we know who someone is. It’s the permission check — can this identity access this resource or perform this action?
Back to the airport: authentication was the passport check. Authorization is the boarding pass and the security guard checking you’re allowed into the business-class lounge. Same person, different gates.
Where each happens in a request
They run at different points in the request pipeline, and knowing the order matters.
401 vs 403 — the classic gotcha
The status codes trip people up, mostly because the names are misleading.
- 401 Unauthorized — we don’t know who you are. The name says “unauthorized” but it really means unauthenticated. Missing or invalid credentials. The fix is: log in.
- 403 Forbidden — we know exactly who you are, and you still can’t do this. Valid identity, insufficient permissions. Logging in again won’t help.
So the only difference is: 401 is “who are you?”, 403 is “not allowed”. If someone hits an admin route with a good token but a regular-user role, that’s a 403, not a 401.
// Express-style middleware showing the two gates
function authenticate(req, res, next) {
const user = verifyToken(req.headers.authorization); // decode + check signature
if (!user) return res.status(401).json({ error: "invalid token" }); // authn fail
req.user = user;
next();
}
function requireAdmin(req, res, next) {
if (req.user.role !== "admin") return res.status(403).json({ error: "forbidden" }); // authz fail
next();
}
RBAC vs ABAC — two ways to model permissions
Once we’re doing authorization, we need a model for who can do what. Two common ones.
RBAC (Role-Based Access Control) — we assign users roles (admin, editor, viewer), and roles carry permissions. Simple and easy to reason about. Most apps start here. The downside is roles explode when rules get granular (“editor, but only for their own team’s docs”).
ABAC (Attribute-Based Access Control) — decisions use attributes of the user, the resource, and the context. Rules like “allow if user.department == resource.department and time is business hours”. Way more flexible, more complex to build and audit.
The only difference in one line: RBAC checks what role you have, ABAC checks the attributes of you plus the thing you’re touching.
Interview soundbite
Authentication verifies identity (who you are), authorization decides permissions (what you can do), and authn always runs first. A failed authn is 401 (we don’t know you — go log in); a failed authz is 403 (we know you, you still can’t). For modeling permissions, RBAC assigns roles, ABAC evaluates attributes and context — RBAC is simpler, ABAC is more granular.