Authentication answers only the first question

A valid session or token establishes an identity to some level of confidence. It does not establish that the identity may perform the requested action. Many serious application failures occur after login because the server trusts an object identifier, role claim, tenant header, workflow state, or client-side decision that the user can influence.

Authorization is better expressed as a relationship: can this subject perform this action on this resource, in this tenant, under these conditions, at this point in the workflow? NIST's attribute-based access-control model describes a similar evaluation across subject, object, operation, and environment attributes.

Testing beyond the happy path means changing one part of that relationship at a time and observing whether the server continues to enforce the intended rule.

Write the rule before testing the endpoint

A route such as GET /projects/123 does not reveal the complete authorization rule. The real rule may be that an active employee with a project membership can view non-archived records belonging to the same organisation, unless the record is restricted to a smaller team. Each condition needs to be explicit before coverage can be judged.

Create a test matrix that names the subject, role, tenant, resource owner, resource state, action, request channel, and expected result. Include deny cases. If the product team cannot state the rule consistently, the problem is already larger than a missing test case.

Roles alone are rarely sufficient. Ownership, delegation, subscription state, geography, data classification, relationship, time, device posture, approval state, or separation-of-duty rules may affect the decision.

Use controlled identities across roles and tenants

At minimum, meaningful horizontal testing needs two identities with the same role and separately owned resources. Vertical testing needs identities with different privileges. Multi-tenant testing needs equivalent roles in separate organisations or workspaces. Administrative, support, service, invited, suspended, and recently removed identities may require their own cases.

Controlled data makes comparison safer and clearer. Create known objects for each identity and tenant, then attempt reads, changes, deletion, sharing, export, and indirect access across the boundary. Record the expected result before sending the request.

When the necessary accounts, tenants, or workflows are unavailable, narrow the conclusion. Lack of a successful bypass is not evidence that an untested boundary works.

Trace the entire object lifecycle

OWASP's API Security Top 10 separates broken object-level, property-level, and function-level authorization because each can fail independently. A user may be prevented from opening another customer's record but still change a hidden property, invoke an administrative action, or infer whether the record exists.

Follow objects from creation through view, update, transition, sharing, export, archive, restore, and deletion. Test single-object and bulk operations. Check search, reports, notifications, attachments, comments, audit logs, imports, integrations, and background jobs that touch the same object.

Identifiers can appear in paths, query strings, bodies, headers, tokens, nested structures, file names, signed links, job parameters, and event messages. Removing a user identifier from the browser request does not remove object authorization risk elsewhere.

Test every enforcement point

Modern systems repeat the same business capability across web interfaces, public and private APIs, mobile endpoints, GraphQL resolvers, webhooks, queues, scheduled jobs, support tooling, and administrative services. A central policy may exist on paper while individual code paths enforce only part of it.

Test direct endpoint access rather than relying on hidden buttons or menus. Change the HTTP method, content type, route version, operation name, and request shape where those paths are in scope. Confirm that downstream services and asynchronous workers re-establish authorization instead of trusting the caller.

Caching, search indexes, exports, and object storage require special care. A primary API may deny access correctly while a cached response, predictable download URL, or exported file exposes the same data outside the normal policy check.

Workflow state is part of authorization

Some actions are allowed only after a sequence of approvals or while an object is in a particular state. Test whether a user can skip a step, repeat a one-time action, reverse an irreversible transition, approve their own request, reuse an expired invitation, or act after membership has been removed.

Business side effects matter. An endpoint may return an error but still enqueue a job, send a notification, change a balance, generate a file, disclose timing, or write an audit event containing sensitive data. Test the system state, not only the HTTP status code.

Concurrency can also change the result. Two individually valid requests may violate a rule when they race. Where the business consequence is material, authorization and state-transition tests should include controlled concurrent or replayed requests.

Treat tenant isolation as a server-side invariant

In a multi-tenant system, the tenant boundary should be derived from trusted server-side context and applied consistently to data access, authorization, storage, caching, logging, messaging, and administration. A client-supplied tenant identifier can help route a request, but it should not be the fact that grants access.

Test cross-tenant reads and writes, relationship creation, invitations, role assignment, search, exports, shared resources, support access, and references to global objects. Check whether a valid identifier from another tenant changes response content, timing, error detail, or side effects.

Shared platform services need explicit rules. Global administrators, support engineers, machine identities, migration tools, and analytics pipelines often cross tenant boundaries legitimately. Their privileges, approvals, logging, and break-glass conditions deserve direct testing.

Negative tests should become engineering assets

A security assessment can reveal a broken boundary, but the durable fix is an executable rule. Convert confirmed cases into automated negative tests close to the authorization decision. Cover representative subjects, actions, resources, tenants, and states, including the failure modes that caused the issue.

Central policy functions and scoped data-access patterns can reduce inconsistency, but centralization is not proof of correctness. Review default behavior, missing attributes, stale role data, policy failures, service-to-service trust, and how exceptions are introduced.

Logs should record enough context to investigate a decision without exposing sensitive data. For material actions, defenders may need the subject, effective role, tenant, resource, action, decision, policy version, and reason for denial or override.

Report coverage, not just findings

The final record should identify the authorization rules assessed, identities and tenants used, object types and lifecycle states covered, channels tested, confirmed failures, blocked attempts, and important gaps. This lets the client understand the evidence behind both findings and clean results.

A strong conclusion does not say that authorization is secure. It says which boundaries behaved as intended under which conditions, which rules failed, and which untested paths prevent broader reliance. That is the difference between a collection of requests and an assurance-ready assessment.

Official sources

Testing must use authorized identities, data, tenants, and environments. The examples describe defensive assessment methods and should be adapted to the agreed scope and safety conditions.