Authorization and access control
Authentication proves who you are. Authorization decides what you may touch. The single most common and most damaging flaw in modern apps is getting the second one wrong: a logged-in user reading or changing data that is not theirs.
Checklist
- Check ownership on every object access. For every route that takes an id (an invoice, a note, a project, a message), confirm the current user owns or may access that specific record before returning or changing it. This is Broken Object Level Authorization (BOLA), also called IDOR, and it is OWASP's number one risk.
- Filter by the owner, not only by the id. A query like
SELECT * FROM invoices WHERE id = ?is an IDOR. Make itWHERE id = ? AND owner_id = ?and return 404 for a miss. - Do not rely on the client to hide things. A hidden button or a missing link is not access control. The check must be on the server.
- Keep authorization when you refactor. Access checks added in one change are often dropped in the next. Re-test ownership after every change to data routes.
- Enforce row-level security in the database where your platform supports it, so a forgotten check in code is still caught by the data layer.
- Gate every admin and internal route. Confirm the caller is actually an admin from a trusted source (a server-side role, not a field the user can set), and keep internal-only routes unreachable from the public internet.
- Isolate tenants. In a multi-tenant app, every query and every file path must be scoped to the caller's tenant through one chokepoint, so one customer can never reach another's data or files.
- Confine file paths. When a request names a file, resolve it and confirm it stays inside the allowed directory, and that the check stops at a path separator so a sibling folder with a longer name cannot be reached.
How to test
- Create two accounts. As account A, request account B's object ids directly. Nothing of B's should come back.
- Call an admin route with a normal user's token. Expect 403.
- Request
../style and sibling-prefix paths on any file endpoint.