Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

AUTHORIZATION AND POLICY · LAB

Find the enforcement and decision points in your tenant, then make one fail

Name the four parts of three real decisions in your tenant, then break the decision point and watch enforcement fail closed with a reference you can trace.

Partly readyUses your lab tenant

The lesson

Builds on: Writing rules with attributes, Designing permissions.

New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.

Partly ready. Most of this lab runs today. Steps that wait on platform features are marked, and Missing infrastructure says what they need.

Your progress

Press Start before you begin. Only events your tenant records after that count, in the order below. Checking reads your tenant's Audit, so you need Audit read access in it.

  1. The management API refuses Ben's audit read

    Recorded as tenant.directory.audit.list rejected.

  2. The local photo API asks the tenant about a token

    Recorded as oauth.introspect succeeded (other_client_token_found) for lab-photo-api.

  3. The token policy refuses a request

    Recorded as oauth.token rejected (policy_denied) for lab-printer-app.

  4. The token policy breaks and the token endpoint fails closed

    Recorded as oauth.token failed (policy_unavailable) for lab-printer-app.

Setup

A general decision service for application data, answering with reasons and policy versions, is G22, and a photo API to enforce it is G3. Your tenant already has three real pairs of asking and answering, and one of them can be broken safely.

  1. Complete Permit and forbid rules in a token policy for lab-printer-app and the helpers, and Read and use the tenant permission catalog for Ben's Help desk role.

  2. Create lab-tmp-policy again (JWT, default key), assign it to lab-printer-app only, and paste this policy, which refuses one recognizable request and allows the rest:

// A decision with a reason the enforcement point can act on.
if (context.scopes.includes('prints.create')) return { allow: false, claims: {} };
return { allow: true, claims: {} };
  1. If lab-photo-api does not exist, create it in OAuth > Clients: confidential, no grants, resource server on.

Walkthrough

  1. The management decision. In Ben's window, open $ISSUER/manage and try the Audit page: refused. In your notes, name its four parts: the enforcement point is the tenant's management API at /api/auth/tenant/...; the decision point is the permission check against current role assignments; the information point is the role and assignment store; the administration point is the Roles page.

Why it matters: the four parts from the lesson exist here, and a real refusal passes through all of them.

  1. The token decision. Name its parts: the enforcement point is /oauth/token; the decision point is the lab-tmp-policy script; the information points are the directory, which supplies subject attributes, and the request itself; the administration point is the access token manager editor. Each save is a recorded tenant.oauth.managers.update with you as actor.

Why it matters: changing this rule is a publish from the administration point, not an edit to the token endpoint's code, as version 14 was published for the Gazette.

  1. The resource decision. Get a token for Ava with authorize "openid photos.read" and redeem. Run the toolkit's local photo API in introspection mode, with lab-photo-api's credentials in your shell, and call it with the token:

export API_ID="<lab-photo-api client ID>"; read -rs API_SECRET
btl-lab resource --port 8766 --mode introspect &
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8766/photos | jq .

The local API decides nothing on its own: it asks /oauth/introspect before serving.

Why it matters: an enforcement point that asks instead of deciding, the lesson's photo API calling its decision service.

  1. Placement. Fill in the lesson's placement table for the token policy, which runs inside the tenant on every issuance, and for introspection, a network round trip to a central service. Note the cost of each decision and what happens to each when its decision point fails.

Why it matters: the same policy can sit in different places, and each placement trades speed, consistency and failure behavior differently.

  1. A decision with a reason. Request openid photos.read prints.create as Ava through lab-printer-app. The token request is refused with invalid_grant and the description "The tenant's access token policy refused to issue this token."

Why it matters: this is a policy denial, a 4xx with a safe message. Compare it with the next step, where the decision point gives no answer at all.

Break it

  1. The decision point fails. Add throw new Error('lab failure'); as the first line of the lab-tmp-policy script and save. Request openid photos.read as Ava. The token endpoint answers HTTP 500 with server_error and a reference_id. Search Logs for that reference: oauth.token failed with reason policy_unavailable.

Why it matters: no answer is a refusal, and it is recorded as an unavailable decision, not as a denial, so operators see an outage rather than a wave of refusals.

  1. The decision point stalls. Replace the first line with while (true) {} and request again. The tenant stops the script at its CPU limit, and the result is the same fail-closed answer.

Why it matters: the enforcement point has a deadline. A stalled decision service must not hold requests forever or let them through.

Restore: remove the line you added, save, and confirm a token is issued again.

Check your work

Press Check my progress. The checks follow Ben's refused audit read, the local API's introspection, the policy denial and the failed policy.

Also confirm by hand:

  • Your four-part maps for the management, token and resource decisions, and your placement table.

  • The reference_id from Break it matched an entry in Logs.

Cleanup

  • Stop the local photo API (kill %1).

  • Assign lab-printer-app back to the default access token manager and delete lab-tmp-policy.

Missing infrastructure

  • G22, a decision service for application data. The lesson's question with subject, action, resource and context sent to a decision endpoint, answers with reason and policy_version, information points for photo status, embargo and device, and a decision cache keyed on everything that affected the answer.

  • G3, a photo API that enforces it. An enforcement point that answers 403 for a denial and 503 for an unavailable decision, so step 5 and Break it become the lesson's two cases on a real resource.

Back to all labs

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

The Lab