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.
- G3 Sample protected resource API; no RFC 9728 protected resource metadata
- G22 End-user authorization engine (PDP, RBAC/ABAC/ReBAC for application data)
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.
Sign in to start this lab and check your progress. Log in or create an account.
The management API refuses Ben's audit read
Recorded as
tenant.directory.audit.listrejected.The local photo API asks the tenant about a token
Recorded as
oauth.introspectsucceeded (other_client_token_found) forlab-photo-api.The token policy refuses a request
Recorded as
oauth.tokenrejected (policy_denied) forlab-printer-app.The token policy breaks and the token endpoint fails closed
Recorded as
oauth.tokenfailed (policy_unavailable) forlab-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.
Complete Permit and forbid rules in a token policy for
lab-printer-appand the helpers, and Read and use the tenant permission catalog for Ben'sHelp deskrole.Create
lab-tmp-policyagain (JWT, default key), assign it tolab-printer-apponly, 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: {} };
If
lab-photo-apidoes not exist, create it in OAuth > Clients: confidential, no grants, resource server on.
Walkthrough
The management decision. In Ben's window, open
$ISSUER/manageand 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.
The token decision. Name its parts: the enforcement point is
/oauth/token; the decision point is thelab-tmp-policyscript; 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 recordedtenant.oauth.managers.updatewith 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.
The resource decision. Get a token for Ava with
authorize "openid photos.read"andredeem. Run the toolkit's local photo API in introspection mode, withlab-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.
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.
A decision with a reason. Request
openid photos.read prints.createas Ava throughlab-printer-app. The token request is refused withinvalid_grantand 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
The decision point fails. Add
throw new Error('lab failure');as the first line of thelab-tmp-policyscript and save. Requestopenid photos.readas Ava. The token endpoint answers HTTP 500 withserver_errorand areference_id. Search Logs for that reference:oauth.tokenfailed with reasonpolicy_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.
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_idfrom Break it matched an entry in Logs.
Cleanup
Stop the local photo API (
kill %1).Assign
lab-printer-appback to the default access token manager and deletelab-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
reasonandpolicy_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.