How it works
The explanation, with examples you can run.
Authentication
Authentication turns a request into an identity: a user ID, a service account, an API client. It uses one or more factors: something you know (a password), something you have (a phone, a security key, a device holding a passkey), something you are (a fingerprint, usually just unlocking a local key). After login, a session cookie or token carries the result, so later requests don't re-authenticate from scratch.
When it fails, respond with 401 and say as little as possible. "Invalid email or password" rather than "no account with that email" avoids helping attackers enumerate accounts.
Authorisation
Authorisation takes the identity and the request and decides yes or no. Common models:
- Role-based (RBAC): users have roles (
admin,editor), roles have permissions. Simple, coarse. - Attribute-based (ABAC): rules over attributes of the user, the resource and the context ("managers may approve expenses under €5,000 in their own department").
- Relationship-based (ReBAC): permissions follow relationships ("can view a document if they are a member of a folder that contains it"), as in Google's Zanzibar and systems inspired by it.
Whatever the model, the decision has to include the specific object. "Is this user an editor?" is not enough; "is this user an editor of this document?" is.
Rules that prevent most mistakes
- Enforce on the server, for every request. The browser, the mobile app and the URL are all under the user's control.
- Deny by default. A route without an explicit rule is refused. Many frameworks let you make this the global default.
- Centralise the decision. One policy function or service, called from everywhere, is easier to test than ownership checks copied into every handler.
- Don't trust identifiers from the client for ownership. Take the user ID from the authenticated session, not from a field in the request body.
- Test it. For each endpoint, a test that a second user gets 403 or 404 on the first user's objects catches the most common bug.
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.