AUTHORIZATION AND POLICY · LAB
Follow a relationship graph to a yes or a no
Planned: store relationship facts for the photo library and follow paths to decisions. Today: query your tenant's real group and manager relationships in both directions with SCIM.
PlannedUses your lab tenant
The lesson
Builds on: Checking access to each object.
New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.
Planned. The core of this lab waits on platform features that are not built yet. The planned walkthrough shows exactly how it will run; Do today is a real exercise you can do now.
- G3 Sample protected resource API; no RFC 9728 protected resource metadata
- G22 End-user authorization engine (PDP, RBAC/ABAC/ReBAC for application data)
Request console
Requests in this lab can be sent from this page to your tenant: open one and choose Send. Fill in the values below first. They stay in this page's memory and are gone when you leave; secrets are never stored or sent anywhere except the request you send.
Setup
The tenant has no relationship-based authorization for application data (G22) and no photo API to protect (G3). Group membership and the SCIM manager attribute are real relationship data, but no access decision reads them. The planned walkthrough shows the full lab as it will run; Do today practices the same questions on the real data.
Complete Object and field checks in the tenant's own APIs for the SCIM clients
lab-scim-readerandlab-provisioning, with SCIM turned on.In Groups, create
lab-tmp-sports-deskand add Ben and Cora.Note the user IDs of Ava, Ben and Cora and the group's ID. In this lab Cora plays Maya the owner, Ava plays Lena the contributor, and Ben plays Omar the editor.
Planned walkthrough
These requests will run once the photo library API and its decision point exist. TOKEN will hold a client credentials token for lab-photo-api, which may write facts and ask questions for this tenant only.
Store the lesson's facts, one tuple each:
POST $ISSUER/lab-api/photos/relationships
Authorization: Bearer $TOKEN
Content-Type: application/json
{"writes":[
{"object":"album:4410","relation":"owner","subject":"user:<Cora's ID>"},
{"object":"album:4410","relation":"contributor","subject":"user:<Ava's ID>"},
{"object":"group:sports-desk-editors","relation":"member","subject":"user:<Ben's ID>"},
{"object":"library:sports","relation":"editor","subject":"group:sports-desk-editors#member"},
{"object":"album:4410","relation":"parent","subject":"library:sports"},
{"object":"photo:9001","relation":"parent","subject":"album:4410"}]}
The answer returns the relationship version the write created.
Read the relation rules in the portal: owner implies editor, editor implies contributor, contributor implies viewer; relations flow from library to album to photo;
photo.viewneeds viewer,photo.uploadcontributor,photo.deleteeditor.Ask whether Ava may view photo 9001:
POST $ISSUER/lab-api/access/v1/evaluation
Authorization: Bearer $TOKEN
Content-Type: application/json
{"subject":{"type":"user","id":"<Ava's ID>"},"action":{"name":"photo.view"},"resource":{"type":"photo","id":"9001"}}
The answer is a permit with the path photo:9001, album:4410, user:<Ava's ID>.
Ask whether Ben may delete photo 9001. A permit, with the five-step path through the group and the Sports library.
Ask whether Ava may delete photo 9001. A deny: Ava is a contributor, and no path reaches her with
editor.Remove Ben's group membership and ask step 4 again. A deny, and the explanation shows which fact was missing.
The reverse question, everything Ava may view:
POST $ISSUER/lab-api/access/v1/search/resource
Authorization: Bearer $TOKEN
Content-Type: application/json
{"subject":{"type":"user","id":"<Ava's ID>"},"action":{"name":"photo.view"},"resource":{"type":"photo"}}
Only album 4410's photos come back, with the index version the answer used.
Do today
The same questions on real relationship data. Get a lab-scim-reader token into SCIM as in the object-checks lab.
From a subject to its objects: which groups does Cora belong to?
GET$ISSUER/scim/v2/Users/<Cora's
Open in console
GET $ISSUER/scim/v2/Users/<Cora's user ID>?attributes=groups HTTP/1.1
Authorization: Bearer $SCIMWhy it matters: this is the reverse question, starting from a person and following every membership outward.
From an object to its subjects: who is in the group?
GET$ISSUER/scim/v2/Groups/<lab-tmp-sports-desk
Open in console
GET $ISSUER/scim/v2/Groups/<lab-tmp-sports-desk ID> HTTP/1.1
Authorization: Bearer $SCIMWhy it matters: the forward direction. A relationship system keeps both directions searchable, because checks and lists start from different ends.
The same membership asked as a filter over all users:
curl -s -G -H "Authorization: Bearer $SCIM" "$ISSUER/scim/v2/Users" \
--data-urlencode 'filter=groups.value eq "<lab-tmp-sports-desk ID>"' --data-urlencode 'attributes=userName' | jq '.Resources[].userName'
Why it matters: the directory answers from an index of memberships rather than reading every user, which is what a list page needs.
Add a fact with an object, a relation and a subject. Get a
lab-provisioningtoken intoSCIMand make Cora Ava's manager:
PATCH$ISSUER/scim/v2/Users/<Ava's
Open in console
PATCH $ISSUER/scim/v2/Users/<Ava's user ID> HTTP/1.1
Authorization: Bearer $SCIM
Content-Type: application/scim+json
{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],"Operations":[{"op":"replace","path":"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager","value":{"value":"<Cora's user ID>"}}]}Then ask for Cora's direct reports with the filter urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager.value eq "<Cora's user ID>", in the same form as step 3. Ava comes back.
Why it matters: "Cora manages Ava" is a stored fact queried both ways, the raw material of relationship-based access, even though no decision reads it yet.
Write Ava, Ben, Cora, the group and the manager fact as tuples in the lesson's notation, such as
group:lab-tmp-sports-desk#member@user:ben, and draw the graph.
Why it matters: with the facts written down, every access question becomes a search for a path, and every missing path is a no.
Break it
Planned: a request with no path is denied, and deleting one fact removes exactly the access that depended on it at the next check.
Today: ask Lab Mail for your Lab Photos group with the same token,
GET $ISSUER2/scim/v2/Groups/<lab-tmp-sports-desk ID>. It is refused, because the token and the relationship data both belong to one tenant.
Check your work
No automated checks: this lab is planned. In the tenant's Audit and Logs, look for the SCIM reads and the manager change made by lab-provisioning, and keep your tuple list and drawing.
Cleanup
Clear Ava's
managerwith a SCIM PATCH that removes the attribute.Delete the group
lab-tmp-sports-desk.
Missing infrastructure
G3 and G22, the photo library API with a relationship store. A per-tenant store of relationship tuples with relation rules, a check endpoint that returns the deciding path, a reverse search endpoint backed by an index with a version, and decision records in tenant Audit. Once it exists, the planned walkthrough runs as written, and its steps get automated checks on the decision records.