Authentication vs Authorization
Two different questions that get confused constantly — "who are you" and "what are you allowed to do."
2 min read
Authentication and authorization are two distinct steps that happen back-to-back on almost every protected request, and mixing them up is one of the most common sources of real security bugs — not because the concepts are hard, but because the words look similar and both get shortened to "auth."
Authentication: who are you
Authentication (authN) verifies identity. It answers "is this really the person/system they claim to be?" — typically by checking a password, validating a token, or completing an OAuth flow.
POST /login
{ "email": "ada@example.com", "password": "••••••••" }
→ 200 OK
{ "token": "eyJhbGciOiJIUzI1NiIs..." }
Once authenticated, the client attaches that proof (a session cookie or a token) to every subsequent request, and the server uses it to establish who is making the request.
Authorization: what are you allowed to do
Authorization (authZ) happens after authentication and answers a completely different question: "now that I know who you are, are you allowed to do this specific thing?"
DELETE /orders/1024
Authorization: Bearer <ada's token>
→ Is this order Ada's own order, or does Ada have an admin role
that permits deleting anyone's order? If not: 403 Forbidden.
A request can be fully authenticated — the token is valid, the server knows exactly who's asking — and still be denied, because authentication alone says nothing about permissions.
Where this goes wrong in real code
The most common real-world bug in this area isn't a broken login system — it's a backend that authenticates correctly but forgets to authorize on a specific endpoint:
GET /orders/1024
If the handler checks "does a valid token exist?" but never checks "does this token's user actually own order 1024?", any logged-in user can read (or with the equivalent DELETE, remove) any other user's data just by changing the ID in the URL. This class of bug is common enough to have its own name: insecure direct object reference (IDOR), and it consistently shows up in security audits of otherwise well-built APIs.
The rule of thumb
Every protected endpoint needs two separate checks, not one:
- Authentication — is there a valid, non-expired credential attached to this request at all?
- Authorization — given who that credential belongs to, is this specific action on this specific resource allowed?
Treating these as one combined "is this request allowed" check is exactly how the IDOR bug above slips through — the fix is to always ask both questions explicitly, on every request, not just at login.
With identity and permissions distinguished, the next lesson looks at the two dominant mechanisms for carrying that identity across requests: sessions and tokens.