Guide
Access control testing: can one tenant read another’s data?
Broken access control is at the top of the OWASP Top 10 for a reason: it’s easy to get wrong and hard to see in ordinary tests. Role-based access testing and tenant isolation testing check it systematically.
What to test
- Role-based access: each role can do what it’s meant to, and is refused the rest (an employee can’t create a company).
- Tenant isolation: in a multi-tenant product, a user of one customer never sees, changes or deletes another customer’s records, also not by guessing an id.
- IDOR (insecure direct object references): an endpoint that takes an id checks that the caller may use that id, not just that the caller is signed in.
- Writes into another tenant: creating, moving or assigning a record with a reference that points at another customer is refused.
- Unauthenticated access: every endpoint that should need a sign-in answers 401 without one.
How to test it
Make test accounts for every role, in at least two tenants, each with a few records of its own.
For every endpoint, call it as each role with its own ids: this should work where the role may do it.
Call it again with ids that only another tenant can see: this should be refused with 403 or 404.
For list endpoints, check the answer only contains the caller’s tenant.
Call every endpoint without a token: it should answer 401, unless it’s meant to be public.
Decide, per finding, whether it’s intended, and keep those decisions as the expected policy.
Common pitfalls
- Testing only with the admin role, which may do everything and so never shows a missing check.
- One tenant in the test data, so isolation can’t be tested at all.
- Checking only that the screen hides a button; the API behind it is what decides.
- Testing it once before a release; access rules change with every new endpoint and role.
Access control testing in Journey Lanes
Flows in Journey Lanes can contain refusals as steps: a step with a status check of 400 or more passes when the API refuses, so “a company admin can’t delete a company” is a step like any other.
A company admin logs in. The company admin sees the orders. The company admin should not be able to delete a company.
- Company Admin
POST /realms/portal/protocol/openid-connect/token200 - Company Admin
GET /api/orders200 - Company Admin
DELETE /companies/:id204
The access audit goes further: every role from your flows signs in and probes every endpoint, with its own ids, with ids only other roles can see, with writes that point at another tenant, with list endpoints, and without a token. Findings are ranked from critical (cross-tenant access) to blocked steps, and your decisions become the access policy the mock backend enforces (access audit).
Questions
What is IDOR?
Insecure direct object reference: an endpoint that takes an id (an order number, a user id) and returns or changes that record without checking that the caller may use it.
What is tenant isolation testing?
Testing that in a multi-tenant product each customer can only reach its own data, by calling every endpoint as a user of one tenant with ids that belong to another.
Can access control tests run on production?
Read probes can, with test accounts in test tenants. Probes that try to change or delete another tenant’s data belong on test environments; Journey Lanes never runs its delete probes on live environments.
Audit access across roles and tenants
Describe a journey per role; the access audit probes every endpoint with every role and tenant.