Authaz logoAuthaz
DocumentationAPI Reference
  • Get Started

    • Authaz
    • Core Concepts
    • Set up your app
    • Quickstart — cURL
  • Authentication

    • Authentication Settings
    • Signup
    • Invitations
    • Password Authentication
    • Multi-Factor Auth
    • Magic Link
    • OAuth / Social Login
    • Passkey (WebAuthn)
    • SAML SSO
    • Machine-to-Machine (M2M)
    • API Keys
  • Authorization

    • Authorization
    • Resources
    • Policies
    • Roles
    • Access Explorer
  • Tenancy

    • Multi-tenancy
    • Tenancy Customization
  • Brand & Host

    • Branding
    • Custom Domains
    • Communications & Email Templates
  • Operate

    • Users
    • Analytics
    • Audit Logs
    • Application Settings
  • SDK Quickstarts

    • Quickstart — Next.js
    • Quickstart — React SPA
    • Quickstart — Hono
    • Quickstart — .NET (Authaz.Sdk)
  • Recipes

    • Recipes & Cookbook
    • Next.js — first integration
    • Next.js — B2B SaaS (multi-tenant)
    • Hono — first integration
    • Hono — B2B SaaS (multi-tenant)
    • React SPA — first integration
    • React SPA — B2B SaaS (multi-tenant)
    • .NET — first integration
    • .NET — B2B SaaS (multi-tenant)
  • Reference

    • Tokens
    • API Reference
    • Errors & Troubleshooting
  • Documentation

    • How Authaz is Built
  1. Authaz
  2. Docs
  3. Authorization
  4. Access Explorer

Authorization

Access Explorer

3 min read·Updated Jun 19, 2026

The Access Explorer (under Authorization → Analyze) answers one question: "Can X do Y on Z?" — and shows the full reasoning trail so you can see exactly why the answer came out that way. It's the page you open when a user reports "I can't do this thing I should be able to do."

Subject:    user_01h7p3n6t8y2qrv4xkc5jbqe7w  (alice@acme.com)
Permission: invoices:update
Tenant:     tenant_acme

→ Allowed
  ├─ Role: Member (global)
  │   └─ Policy: Invoices Writer
  │       └─ Permission: invoices:update  ✓
  └─ Direct grant: editor on invoices/inv_2024_03  ✓

The form on the page mirrors this output — pick the user, the permission, optionally a tenant or a specific resource ID, hit Check, see the verdict and the trace.

Where it lives#

Dashboard → Application → Authorization → Access Explorer. The form takes:

FieldWhat it accepts
UserA user from the application's user pool. Search by email or paste an ID.
PermissionAny resource:action string from the catalog. Auto-completes against the Resources you've defined.
Previous
Roles
Next
Multi-tenancy
Tenant (optional)When set, the check is scoped to that tenant — same as production.
Resource ID (optional)Set this when you're investigating a direct grant on a specific resource instance.

After checking, the page shows:

  • Verdict — Allowed or Denied, with the resolution latency in milliseconds.
  • Role trace — every role assignment that contributed (or didn't) to the answer, expanded down to the policy and permission.
  • Policy trace — every policy considered, marked as containing the permission or not.
  • Relationship trace — direct grants on this resource (when a resourceId is provided), with the relation that grants the action.

How to read a trace#

A successful check shows the path that granted the permission. Each step has a checkmark; missing checkmarks mean the path didn't contribute. A typical "yes" looks like:

✓ Allowed (1.2 ms)

User: alice@acme.com  →  invoices:update  in tenant_acme

Roles assigned:
  ✓ Member (global)
      Policies attached: 2
      ✓ Invoices Writer
          Permissions: invoices:create, invoices:read, invoices:update, invoices:send
                       └─ matched: invoices:update
      • Reports Viewer
          (no matching permission)
  • Viewer (tenant_initech)
      (different tenant — not considered)

Direct grants on this resource: none.

A denial trace lists every place the permission could have come from but didn't:

✗ Denied (0.9 ms)

User: alice@acme.com  →  invoices:delete  in tenant_acme

Roles assigned:
  • Member (global)
      Policies attached: 2
      • Invoices Writer  (no matching permission — closest: invoices:update)
      • Reports Viewer    (no matching permission)
  • Viewer (tenant_acme)
      Policies attached: 1
      • Invoices Reader   (no matching permission — read-only)

Direct grants on this resource: none.

Suggestion: attach a policy with `invoices:delete` to one of Alice's roles,
or grant her `owner` on this specific invoice via a direct relationship.

The "closest match" hint and the suggestion are heuristics — they don't always identify the exact fix, but they typically point at the right policy.

Programmatic access#

The Access Explorer is a UI on top of POST /api/v1/authorization/explain. You can call it directly when building your own admin tools:

curl -X POST https://your-app.authaz.io/api/v1/authorization/explain \
  -H "X-API-Key: $AUTHAZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user_01h...",
    "resource": "invoices",
    "action": "update",
    "tenantId": "tenant_01h...",
    "resourceId": "inv_2024_03"
  }'
{
  "allowed": true,
  "roleTrace": [
    {
      "roleId": "role_member",
      "roleName": "Member",
      "direct": true,
      "includedFrom": []
    }
  ],
  "policyTrace": [
    {
      "policyId": "pol_invoices_writer",
      "policyName": "Invoices Writer",
      "containsPermission": true,
      "permissions": ["invoices:create", "invoices:read", "invoices:update", "invoices:send"]
    }
  ]
}

/explain is heavier than /check — it loads every role, every policy, and every relevant relationship, not just enough to short-circuit. Use it for debugging and audit UIs, not for hot-path checks.

Common investigations#

"This user should have access — why doesn't it work?" Open Access Explorer with their user ID and the permission they need. The denial trace usually points at the missing policy or the wrong tenant.

"This user shouldn't have access — why do they?" Same form, the verdict is "Allowed", scan the trace for the role or direct grant that's responsible. If it's a role you didn't expect, check the role's assignments page.

"Did the recent role change break anything?" Check a few representative users for the permissions you cared about, both before and after the change. Saves emergencies after a Friday refactor.

"My API call returns Forbidden but the user is in the right group." Compare the request — Bearer token, tenant context, resource ID — against the explorer's check. Half the time it's a missing tenantId in the API call, not a permissions issue.

Latency expectations#

  • /check (and the Access Explorer's verdict): typically <1 ms, p99 in single-digit milliseconds.
  • /explain (the trace): typically 5–20 ms — it's reading more state.

Both are read-only. Use either as freely as you'd use a database SELECT — Authaz is built to handle the volume.

Next steps#

  • Roles — fix the most common cause of unexpected denials (missing role).
  • Policies — fix the second-most-common cause (policy missing the permission).
  • Resources — when neither of the above applies, the permission may not be in the catalog.