Tags: web-dev concept

Authentication vs Authorisation

Date: 2026-08-17


Authentication is who you are; authorisation is what you may do. They’re separate systems, they fail separately, and the second is where nearly every real breach happens — because authentication is a solved problem people buy, and authorisation is bespoke logic people write.


Authentication (authn) establishes identity. Authorisation (authz) determines permissions.

AUTHENTICATION      AUTHORISATION
who are you?        what may you do?
login               permission check
once per session    on EVERY request
401 Unauthorised    403 Forbidden
  ← misnamed;         ← correctly named
    means "not
    authenticated"

HTTP’s 401 is historically misnamed. It means “authenticate and retry”; 403 means “authenticated, still not allowed” — HTTP Semantics.

The factors

SOMETHING YOU KNOW    password, PIN
SOMETHING YOU HAVE    phone, hardware key
SOMETHING YOU ARE     fingerprint, face

Multi-factor means factors from different categories. A password plus a security question is one category twice, and adds very little.

STRENGTH, ROUGHLY

SMS codes        weakest — SIM swapping,
                 interception
TOTP app         good
push approval    good, vulnerable to
                 fatigue attacks
passkeys /       strongest — phishing-
WebAuthn         resistant by design,
                 because the credential is
                 bound to the origin

Passkeys are phishing-resistant for a structural reason: the credential only works on the domain it was created for, so a lookalike site cannot use it. No amount of user education achieves that.

Why authorisation is where breaches happen

Authentication is largely a solved problem you can buy. Authorisation is business logic, written per application, and rarely tested adversarially.

The most common failure has a name — broken object level authorisation, and it’s mundane:

GET /api/orders/1042
  → checks: are you logged in?  ✓
  → does NOT check: is order 1042 yours?

change the number → read someone
else's order

Authentication passed. Authorisation was never performed. This is consistently among the most commonly found web vulnerabilities, and it appears in mature codebases constantly because each endpoint has to remember the check.

Related shapes:

FUNCTION-LEVEL     the admin endpoint is
                   hidden in the UI but
                   not protected server-side

MASS ASSIGNMENT    POST includes
                   {"role": "admin"} and
                   the ORM writes it

CLIENT-SIDE ONLY   the button is hidden,
                   the API is open

Anything enforced only in the UI is not enforced. The browser is the attacker’s tool, not your control point.

Models

RBAC   role-based
  user has roles, roles have permissions
  simple, ubiquitous, coarse

ABAC   attribute-based
  rules over attributes of user,
  resource and context
  flexible, harder to reason about

ReBAC  relationship-based
  "can edit if they own it, or if their
   team owns it"
  fits real products well

Most applications need “does this user own this thing”, which is relationship-based, and end up bolting it onto RBAC one endpoint at a time. Recognising that early saves a lot of scattered checks — Authorisation Models for the models in full and where the check belongs.

Making it hard to get wrong

  • Deny by default. Authorisation should be a middleware or policy layer that must be explicitly satisfied, not a check each route remembers to include
  • Authorise the object, not just the route. Fetch the resource, then check ownership, on every request
  • Scope the query instead of checking after. WHERE user_id = ? in the query cannot be forgotten downstream, whereas a post-fetch check can
  • Never trust a client-supplied identity. The user ID comes from the session, never from the request body
  • Allow-list the fields you accept. Mass assignment is prevented by never binding raw input to a model
  • Test with a second account. The single most effective check: log in as user B and request user A’s resources by ID

Where it sits

Authentication produces a credential; authorisation consumes it on every request — Sessions and Tokens, OAuth and OpenID Connect, Common Vulnerabilities. Where each lives in a system is Authentication Architecture.