ACC-77Required
Check ownership on every record
Before returning or changing a record, check on the server that it belongs to the logged-in user or their team.
How to do it
Look records up with the user in the query, such as WHERE id = $1 AND owner_id = $2. Answer 404 for records the user may not see, so they learn nothing. Put the check in the data access layer, so a new route cannot forget it. Random IDs make guessing harder, but they are no defence alone. For APIs, see object authorisation.
Examples
HTTP example
GET /api/invoices/2002 HTTP/1.1
Authorization: Bearer <token of user A, who owns invoice 2001>
HTTP/1.1 404 Not Found
How to check
Log in as two test users. With user A's token, request, change and delete user B's records by ID. Try list, export and search routes, IDs inside request bodies and GraphQL queries too. Every request returns 404 or 403, and lists show only A's records.
Sources
Related rules
- API-40 Authorise every object in API design
- API-96 Limit the depth and cost of every GraphQL query in API design
- DAT-7 Keep each customer's data apart in Data and databases
- DAT-83 Turn on row-level security for every table in Data and databases
- ACC-35 Start with roles and add record rules only when needed in Accounts and identity
- ACC-36 Test every role and a signed-out visitor against every action in Accounts and identity
- NTF-36 Check the recipient may still see the item when you send in Notifications
- NTF-31 Store every notification in a server-side inbox in Notifications
- AGT-12 Check the caller's rights on every handle in Agents as users
- TKO-7 Fix in risk order in Codebase takeover
- ECM-42 Let each seller reach only their own orders and customers in E-commerce and fulfilment
- SRH-10 Filter search results by access inside the query in Search
- TDD-11 Test the access rules on the running product in Technical due diligence
- APS-101 Decide access in one policy module in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/accounts/roles-and-permissions/object-access">Agent Wranglers accounts and identity playbook</a>. In code you write, add a comment next to it with the same link.