Authentication vs Authorization: AuthN vs AuthZ (and Why 401 ≠ 403)

Authentication and authorization sound the same and get mixed up constantly, but they answer two different questions: who are you, versus what are you allowed to do. Here's the difference that actually prevents security bugs — credentials and the three factors that build MFA, roles and scopes and policies checked on every request, the classic 401-vs-403 trap, and how the exact same split governs API keys and tool permissions for LLM agents.

Banner

Prefer to watch? ▶ AuthN vs AuthZ in 90 seconds ✈ Telegram

They sound almost identical, they're both abbreviated "auth," and engineers blur them constantly — which is a problem, because the confusion shows up later as security bugs. Authentication and authorization answer two completely different questions, and they happen in a fixed order.

The one-line mental model:

  • Authentication (AuthN) asks: who are you? You prove your identity.
  • Authorization (AuthZ) asks: what are you allowed to do? The system checks your permissions.

Think of a hotel. Showing your passport at the front desk to get a key card is authentication — proving who you are. The key card then opening your room but not the penthouse or the staff office is authorization — what that identity is permitted to access. You always show the passport first; the door checks come after.


Authentication: prove who you are

Authentication is how you prove your identity to a system. You hand over credentials — a password, a one-time code, a fingerprint — the server verifies them, and if they check out, it now knows it's really you.

The critical property: authentication always happens first. No identity, nothing else matters. You can't decide what someone is allowed to do until you know who they are.

POST /login HTTP/1.1
Content-Type: application/json

{ "email": "vahid@example.com", "password": "•••••••••" }

200 OK
{ "token": "eyJhbGc..." }   ← proof of identity for the next requests

That token (a session cookie or a JWT) is the server saying "I've confirmed who you are — show me this on every future request so I don't have to re-check your password each time."


The three factors (and how you get MFA)

There are exactly three kinds of evidence you can use to prove identity, and security people call them factors:

  • Something you know — a password, a PIN, a passphrase.
  • Something you have — your phone, a hardware security key, a TOTP authenticator app.
  • Something you are — a fingerprint, a face scan, an iris — biometrics.

A password alone is single-factor. The moment you combine two or more different factors — say a password plus a code from your phone — you get multi-factor authentication (MFA). The reason MFA is so much stronger is simple: an attacker who phishes your password still doesn't have your physical phone or your fingerprint. They'd have to defeat two independent categories at once.

Rule of thumb: a stolen password is one factor compromised. MFA means one stolen factor isn't enough.


Authorization: decide what you can do

Once the server knows who you are, authorization decides what you're allowed to do. Same identity, different permissions: can this user read this record, edit that one, delete the other?

Authorization is usually expressed as one of:

  • Roles (RBAC)admin, editor, viewer. The role carries a bundle of permissions.
  • Scopes — fine-grained grants like repo:read or billing:write, common in OAuth tokens.
  • Policies — rules evaluated against attributes ("a user may edit a document only if they own it").
DELETE /posts/42 HTTP/1.1
Authorization: Bearer eyJhbGc...      ← we know WHO you are (authenticated)

403 Forbidden
{ "error": "viewer role cannot delete posts" }   ← but you're not ALLOWED (authorization)

The key thing people forget: authorization is checked on every single request, not just once at login. Being logged in doesn't mean you're allowed to do the next thing you try. Identity is established once; permission is verified every time.


The twist everyone trips on: 401 vs 403

Here's where the confusion turns into actual bugs. HTTP has two status codes that map exactly onto this split — and one of them is misnamed.

  • 401 Unauthorized → we don't know who you are yet. Your credentials are missing or invalid. This is an authentication failure. The correct fix is log in.
  • 403 Forbidden → we know exactly who you are, you're just not allowed to do this. This is an authorization failure. Logging in again won't help — you lack the permission.

The trap is the name: HTTP labeled the authentication error "Unauthorized," even though it's really about authentication, not authorization. So 401 = "authenticate, please," and 403 = "authenticated, but forbidden." Same request, completely different failure, completely different fix.

401 Unauthorized403 Forbidden
Really meansNot authenticatedAuthenticated, not permitted
Which "auth"AuthN (who are you?)AuthZ (what can you do?)
Does the server know you?NoYes
How to fix itLog in / send valid credentialsGet the right role/scope — re-login won't help

The same split in AI / LLM systems

If you build with LLMs and agents, this isn't abstract trivia — it's the security model for your whole stack, and the two halves stay perfectly distinct.

Authentication in an AI app is mostly about API keys and tokens. Your service authenticates to the model provider with a secret key; your users authenticate to your app with sessions or JWTs. The hard-won lesson here is that those provider keys are identity — leak one and someone is now you to the LLM provider, spending your budget. That's why keys belong in secret stores, never in client code or environment variables that leak through process inspection.

Authorization is where agentic systems get genuinely interesting. An LLM agent with tools is an identity that can act — call functions, hit internal APIs, run queries. The dangerous shortcut is letting the agent inherit broad, ambient permissions just because it's "trusted." It shouldn't be. The same RBAC-and-scopes thinking applies:

  • Give each agent or tool the narrowest scope it needs — read-only where it only needs to read, a single namespace where it only touches one dataset.
  • Authorize per tool call, on every request, exactly like a 403 check — "is this identity allowed to run this tool with these arguments?" — rather than trusting the model's intent.
  • Keep the user's authorization separate from the agent's: a user asking a question should never let the agent do something the user themselves isn't permitted to do (the classic confused deputy problem).

Protocols like MCP and OAuth-scoped tokens exist precisely so an agent authenticates once but is authorized narrowly, per action. Same two questions as a plain web app — who are you? then what may you do? — just with a model in the loop that can take actions on its own.


Authentication vs authorization at a glance

Authentication (AuthN)Authorization (AuthZ)
Question it answersWho are you?What are you allowed to do?
What it checksCredentials (the three factors)Roles · scopes · policies
When it runsFirst, to establish identityOn every request, after identity
Fails with401 Unauthorized403 Forbidden
Stronger byAdding factors (MFA)Least privilege, narrow scopes

The verdict

  • Authentication is who you are — prove identity with credentials, and combine two or more factors to get MFA.
  • Authorization is what you're allowed to do — enforced with roles, scopes, and policies, and checked on every request, not just at login.
  • The order is fixed: authenticate first, then authorize. Identity, then permissions.
  • Remember the misnomer: 401 is an authentication error ("we don't know you — log in"), 403 is an authorization error ("we know you, you're just not allowed"). Reaching for the wrong one is how access-control bugs ship.

Get these two straight and your whole security model gets simpler — for a REST API, an OAuth flow, or an LLM agent reaching for a tool. Which one bit you last?

Want the 90-second visual version? Watch the reel.

Authentication vs Authorization: AuthN vs AuthZ (and Why 401 ≠ 403) | Vahid Aghajani