Authentication vs Authorization
Authentication answers "who are you?" and authorization answers "what are you allowed to do?". They are separate steps, and many access-control bugs come from mixing them up or skipping the second one.
Two different questions
| Authentication (authn) | Authorization (authz) | |
|---|---|---|
| Question | Who are you? | What may you do? |
| Happens | First, at login or per request | After identity is known, on every action |
| Examples | Password, MFA code, certificate | Roles, permissions, ownership checks |
| Typical HTTP failure | 401 Unauthorized (really “unauthenticated”) | 403 Forbidden |
How identity is carried
With a session cookie, the server stores a session after login and gives the browser an opaque ID in a cookie. This is simple and easy to revoke. Set the HttpOnly, Secure and SameSite cookie attributes.
A token, often a JWT, is signed by the server and sent by the client in an Authorization: Bearer <token> header. Services can verify it without a shared session store, but it is harder to revoke before it expires.
An API key is a long-lived string that identifies an application or user. It is easy to use and easy to leak, so treat it as a secret.
OAuth 2.0 lets an app act for a user without seeing their password, and OpenID Connect adds identity on top. SSO and MFA build on these ideas.
Authorization checks
- Check permissions on the server for every request. Hiding a button in the UI is not access control.
- Check ownership as well as roles: may this user read this record? Missing object-level checks are a classic flaw.
- Default to deny, and grant the least privilege needed.
- Never trust identity or role values sent by the client without verifying them.
- Keep tokens and passwords out of URLs and logs, and use HTTPS (see TLS and HTTPS Basics).
Do not write your own password handling or token signing; use your platform’s tested libraries. For stored passwords, see Password Security.
Try it
Using an API client or the browser developer tools (see API Testing Tools), call a protected endpoint with no credentials, then with valid ones, and note the status codes. Then request another user’s resource and see which code you get.
Common mistakes
- Checking that the user is logged in but not that they own the record.
- Hiding a button in the UI and treating that as access control.
- Trusting identity or role values sent by the client.
- Putting tokens or passwords in URLs and logs.
Check yourself
- A user is logged in and requests another user's order. Which check should stop them, and which status code fits?
- Why is a JWT harder to revoke than a session ID?
- Which cookie attributes should a session cookie set?