Authentication proves something about the caller. Authorization determines whether that caller may retrieve this customer's reports or perform this operation. A valid API credential must not become a shortcut around tenant boundaries. Begin with a permission matrix before adding endpoints or background jobs.
Bind identity to the requested object
Resolve the caller's identity through the supported authentication mechanism, then obtain its authorized tenant and operation scopes from trusted server-side state. Treat a tenant ID in a URL or request body as a requested target, not proof of permission. Check the report, export job and download artifact against the caller's actual grant.
OWASP's Authorization Cheat Sheet recommends least privilege, deny by default and permission validation on every request. Apply those principles to asynchronous workers and download links as well as the first API call. An export created legitimately must not later be downloadable by a different tenant because its object ID is easy to guess.
Separate read access from change authority
A report reader may retrieve approved domain data but should not automatically gain DNS write permission. A DNS operator may need no access to stored report history. An auditor may require a restricted evidence view rather than raw messages. Document each role's allowed objects and operations, and keep secret management outside ordinary logs and exports.
Suppose an automation credential is approved only to read tenant A’s reports. A DNS change for tenant A and a report read for tenant B both need denial under that grant, despite valid authentication. A separate, explicitly approved operator grant would need its own object and operation checks. These are hypothetical expected decisions, not an implemented permission matrix or a description of EmailAuth roles.
Make negative tests part of acceptance
Run the allowed same-tenant report read, then change only the requested tenant. Repeat with a missing read scope and with a revoked principal. Also plan real tests for object-level IDs, stored exports, queued jobs and changed group membership. Use authorized synthetic tenants and harmless data rather than probing another customer's account.
Record the actual decision and any disclosed response fields for each authorized test. A rejected request must not leak private object details through metadata, counts, download links or cached results. Include a valid scoped read to distinguish correct enforcement from an endpoint that denies everyone. No token system, OAuth flow or production authorization test is supplied or executed here.
Operate the grant through its lifecycle
Record grant owner, approved purpose, tenant scope, expiry or review trigger and revocation path. Store credential material in the approved secret system, rotate under a controlled procedure and audit use without recording the secret itself. Recheck authority when executing delayed work; a queued task should not retain permissions indefinitely after revocation.
Review the underlying data sensitivity. RFC 9990 describes aggregate report content and security considerations; report metadata still deserves controlled disclosure. On an authorization failure, return an appropriate denial without confirming another tenant's private objects. If cross-tenant data is discovered, contain the exposure and invoke the organization's incident procedure. Do not simply alter the UI and assume the API is safe.
OWASP’s multi-tenant guidance, especially its asynchronous-work, cache/session and file-storage sections, supports enforcing scope beyond the initial request and rechecking time-sensitive permissions during delayed execution.