Skip to main content

Test application authorization

Verify object, property, action, workflow, tenant, and administrative authorization with a systematic identity and state matrix.

Learning outcomes

  • Build an authorization matrix from subjects, objects, actions, properties, context, and state.
  • Test every decision with positive, horizontal, vertical, cross-tenant, stale, and unauthenticated cases.
  • Verify that user interfaces, APIs, workers, exports, and administrative paths enforce one policy intent.
  • Connect route decisions to application state changes and durable evidence.

Protection need

Select one application with several identities, tenants, object types, and sensitive actions. The test objective is not only to confirm that unauthenticated users are blocked. It is to prove that each authenticated subject can perform only the permitted action on the permitted object and properties in the permitted state and context.

Inventory every access path:

  • Browser pages and forms.
  • Public and private APIs.
  • Mobile or desktop clients.
  • Batch, queue, and event consumers.
  • Import, export, report, and search functions.
  • Administrative, support, recovery, and impersonation tools.
  • Direct object storage and generated links.
  • Old API versions, alternate content types, and method overrides.

List human, service, workload, and agent identities. Include anonymous, disabled, suspended, invited, cross-tenant, support, administrator, emergency, and stale-session states.

Security objectives and requirements

Express each decision as a tuple:

subject, actor, tenant, object, property, action, context, object state, policy version -> allow or deny

Separate these dimensions:

  • Object-level authorization: may the subject act on this exact record?
  • Property-level authorization: may the subject read or change this field?
  • Function-level authorization: may the subject invoke this operation?
  • Tenant authorization: do the subject and object share the required tenant relation?
  • Workflow authorization: is the transition permitted from the current state and approval history?
  • Delegation: may the actor act for the subject, with this scope and expiry?
  • Administrative authority: does the elevated path require fresh authentication, approval, and evidence?

Build a decision table from the product policy and data model. For every allow row, derive deny rows by changing one security-relevant dimension. Do not infer authorization from a route name, hidden button, object identifier shape, or client-supplied role.

The authoritative service evaluates current server-side facts at the action. It retrieves the object within the tenant and permission scope instead of loading any object and checking only after sensitive fields are exposed. It denies an unknown action, state, role, relation, or policy result.

Security invariants and evidence

Important invariants include:

  • Every data read and state change has an application decision for the exact object and action.
  • A caller cannot change tenant, owner, role, price, approval, or protected property through mass assignment.
  • The same policy intent applies through browser, API, worker, export, and administrative paths.
  • Route access never substitutes for object permission.
  • A policy or relationship change takes effect within the stated revocation bound.
  • A denied action produces no successful downstream state change.

Automate the decision matrix at the service boundary. Seed known identities and objects with explicit relationships. Use an independent oracle derived from the policy model, not the same helper that production code calls. Assert response, returned fields, persistent state, external effects, and decision evidence.

Keep a small set of end-to-end tests through the deployed route. They prove identity propagation, route policy, header trust, direct-path isolation, application decisions, and final evidence work together.

Failure cases

Test systematic mutations:

  • Replace the object with another object owned by the same role, another user, another tenant, or no owner.
  • Change one protected property in an otherwise allowed update.
  • Invoke an administrator function with a normal user and a service identity.
  • Reuse a deleted, disabled, moved, or expired subject and stale session.
  • Skip, repeat, or reorder workflow transitions and approvals.
  • Race two state changes against one version or quota.
  • Submit extra fields, duplicate fields, alternate content types, batch items, and nested objects.
  • Access export, search, count, error, and metadata responses that can reveal unauthorized records.
  • Reach the origin, old route, worker, storage object, or support function directly.
  • Forge identity headers or use a valid assertion for the wrong audience.

Do not stop at a denial status. Check that no data, count, timing distinction, queued work, notification, or partial state escaped.

Design tradeoffs and residual risk

A centralized authorization service can improve consistency and adds availability, latency, cache, and freshness dependencies. Local checks can use rich object state and can drift across code paths. Data-layer tenant filtering reduces accidental exposure and cannot express every business transition. Tests generated from one matrix improve coverage and can share a mistaken policy assumption.

Use independent review and selected adversarial tests for high-impact decisions. Record any path that cannot use the normal policy mechanism, including its narrower compensating control and retirement plan.

Pomerium boundary

Pomerium can authenticate the session and authorize access to a named route using identity and request context. It can block unauthorized users before the application and provide signed identity context.

The application owns records, fields, business actions, tenant relations, workflow state, approvals, and final effects. It must verify the signed assertion where used and must not trust caller-supplied identity headers. The deployment must prevent direct access around the route or require an equivalent authenticated application boundary.

Exercise

Choose one object with at least four actions and three roles. Create:

  1. An allow matrix for subjects, objects, properties, actions, states, and context.
  2. At least three deny mutations for every allow row.
  3. Cross-tenant, stale-session, disabled-user, service-identity, and administrator cases.
  4. Tests through the service boundary and five end-to-end tests through the deployed route.
  5. Assertions for response, returned fields, persistent state, external effects, and decision logs.

Run the suite against every API version and alternate path. Fix the policy model when two paths produce different decisions for the same tuple.

Evaluation checklist

  • Does the model include subject, actor, tenant, exact object, property, action, context, state, and policy version?
  • Is every allow row paired with horizontal, vertical, cross-tenant, stale, and unauthenticated deny cases?
  • Do browser, API, worker, export, support, and administrative paths apply one policy intent?
  • Are extra fields, batches, nested objects, counts, search, and error responses covered?
  • Do tests assert final state and external effects as well as the HTTP result?
  • Does the deployed test prove identity assertion validation and direct-origin isolation?
  • Is revocation latency measured for identity, role, relation, and policy change?

Next learning unit

Sources and further reading

Keep learning

Software and Application Security

Business Logic Abuse

Protect workflow order, object state, quotas, prices, approvals, and other business invariants from valid-looking misuse.

Learn this term
Authorization and PolicySecurity Operations and Risk

Authorization Decision Log

Record enough structured evidence to explain and test an access decision without storing credentials or excess personal data.

Learn this term
Authorization and PolicySecurity Operations and Risk

Authorization Drift

Authorization drift is the gap that develops when effective access no longer matches intended access.

Learn this term

Get a Personalized Demo

Schedule a Call with a Pomerium Engineer

Get a Demo