KBAC: Relationship-Based Authorization with authZEN API
This example demonstrates KBAC (Knowledge-Based Access Control) using the authZEN standard API:
Policy logic: A Person can DRIVE a Car if they have a DRIVES relationship to that Car in the graph.
authZEN operations demonstrated:
1. Evaluation: "Can Alice drive Car1?" -> true/false
2. Action Search: "What actions can Alice perform on Car1?" -> ["drive"]
3. Resource Search: "Which cars can Alice drive?" -> ["Car1", "Car2"]
4. Subject Search: "Who can drive Car1?" -> ["Alice", "Bob"]
authZEN is an OpenID standard for authorization APIs (https://openid.net/specs/authorization-api-1_0-03.html).
Use case
Scenario: A car-sharing application needs to verify driving permissions.
Graph structure:
- Person(Alice) -[DRIVES]-> Car(Car1)
- Person(Alice) -[DRIVES]-> Car(Car2)
- Person(Bob) -[DRIVES]-> Car(Car1)
Authorization questions the app can ask:
1. "Can Alice drive Car1?" -> Yes (DRIVES relationship exists)
2. "Can Alice drive Car3?" -> No (no DRIVES relationship)
3. "What can Alice do with Car1?" -> ["drive"]
4. "Which cars can Alice drive?" -> ["Car1", "Car2"]
5. "Who can drive Car1?" -> ["Alice", "Bob"]
Use this pattern for: vehicle access, device permissions, resource sharing, role-based access.

Requirements
Prerequisites:
- ServiceAccount credentials: For creating policies (Bearer token)
- AppAgent credentials: For data ingestion and authorization queries (X-IK-ClientKey)
Required API access:
- POST /capture/v1/nodes/ and /capture/v1/relationships/ (graph data)
- POST /configs/v1/authorization-policies (create policy)
- POST /access/v1/evaluation (single authorization check)
- POST /access/v1/search/action (what actions are permitted?)
- POST /access/v1/search/resource (which resources can be accessed?)
- POST /access/v1/search/subject (who can access this resource?)
Steps
Step 1: Ingest Authorization Graph Data
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: POST Person and Car nodes, DRIVES relationships
- Result: Graph ready for authorization queries
Step 2: Create KBAC Policy
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST policy defining: Person can DRIVE Car if DRIVES relationship exists
- Result: Policy ID returned
Step 3: Run authZEN Evaluation
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: POST to /access/v1/evaluation with subject, action, resource
- Input: {subject: "Alice", action: "drive", resource: "Car1"}
- Result: {decision: true} or {decision: false}
Step 4: Run authZEN Searches
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action Search: "What can Alice do with Car1?" -> ["drive"]
- Resource Search: "Which cars can Alice drive?" -> ["Car1", "Car2"]
- Subject Search: "Who can drive Car1?" -> ["Alice", "Bob"]
Step 5: Cleanup
- Action: DELETE policy configuration
Step 1
Capture the nodes needed for this use case.
{
"nodes": [
{
"external_id": "alice",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "alice@email.com"
},
{
"type": "given_name",
"value": "Alice"
},
{
"type": "last_name",
"value": "Smith"
}
]
},
{
"external_id": "knightrider",
"type": "Person",
"is_identity": true,
"properties": [
{
"type": "email",
"value": "knightrider@demo.com"
},
{
"type": "name",
"value": "Michael Knight"
}
]
},
{
"external_id": "satchmo",
"type": "Person",
"is_identity": true,
"properties": [
{
"type": "email",
"value": "satchmo@demo.com"
},
{
"type": "name",
"value": "Louis Armstrong"
}
]
},
{
"external_id": "karel",
"type": "Person",
"is_identity": true,
"properties": [
{
"type": "email",
"value": "karel@demo.com"
},
{
"type": "name",
"value": "Karel Plihal"
}
]
},
{
"external_id": "kitt",
"type": "Car",
"is_identity": false,
"properties": [
{
"type": "manufacturer",
"value": "pontiac"
},
{
"type": "model",
"value": "Firebird"
}
]
},
{
"external_id": "cadillacv16",
"type": "Car",
"is_identity": false,
"properties": [
{
"type": "manufacturer",
"value": "Cadillac"
},
{
"type": "model",
"value": "V-16"
}
]
},
{
"external_id": "harmonika",
"type": "Bus",
"is_identity": false,
"properties": [
{
"type": "manufacturer",
"value": "Ikarus"
},
{
"type": "model",
"value": "280"
}
]
},
{
"external_id": "listek",
"type": "Ticket",
"is_identity": false
},
{
"external_id": "airbook-xyz",
"type": "Laptop",
"is_identity": false
}
]
}Capture the relationships needed for this use case.
{
"relationships": [
{
"source": {
"external_id": "knightrider",
"type": "Person"
},
"target": {
"external_id": "kitt",
"type": "Car"
},
"type": "DRIVES"
},
{
"source": {
"external_id": "satchmo",
"type": "Person"
},
"target": {
"external_id": "cadillacv16",
"type": "Car"
},
"type": "DRIVES"
},
{
"source": {
"external_id": "karel",
"type": "Person"
},
"target": {
"external_id": "listek",
"type": "Ticket"
},
"type": "HAS"
},
{
"source": {
"external_id": "listek",
"type": "Ticket"
},
"target": {
"external_id": "harmonika",
"type": "Bus"
},
"type": "FOR"
},
{
"source": {
"external_id": "karel",
"type": "Person"
},
"target": {
"external_id": "airbook-xyz",
"type": "Laptop"
},
"type": "OWNS"
},
{
"source": {
"external_id": "alice",
"type": "Person"
},
"target": {
"external_id": "airbook-xyz",
"type": "Laptop"
},
"type": "OWNS"
},
{
"source": {
"external_id": "knightrider",
"type": "Person"
},
"target": {
"external_id": "kitt",
"type": "Car"
},
"type": "OWNS"
},
{
"source": {
"external_id": "alice",
"type": "Person"
},
"target": {
"external_id": "cadillacv16",
"type": "Car"
},
"type": "DRIVES"
}
]
}Step 2
KBAC Policy which rules that a Person node can drive a car if the Person node has a relation DRIVES with a Car node.
{
"meta": {
"policy_version": "2.0-kbac"
},
"subject": {
"type": "Person"
},
"actions": [
"CAN_DRIVE"
],
"resource": {
"type": "Car"
},
"condition": {
"cypher": "MATCH (subject:Person)-[:DRIVES]->(resource:Car)"
}
}Request to create the KBAC Policy configuration using REST.
{
"project_id": "your_project_gid",
"description": "description of policy",
"display_name": "policy name",
"name": "policy-name",
"policy": "{\"meta\":{\"policy_version\":\"2.0-kbac\"},\"subject\":{\"type\":\"Person\"},\"actions\":[\"CAN_DRIVE\"],\"resource\":{\"type\":\"Car\"},\"condition\":{\"cypher\":\"MATCH (subject:Person)-[:DRIVES]->(resource:Car)\"}}",
"status": "ACTIVE",
"tags": []
}Request to create the KBAC Policy configuration using Python.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = "{"description": "",
"display_name": "",
"name": "",
"policy": "",
"project_id": "",
"status": "ACTIVE",
"tags": [
""
]}"
headers = {
'Content-Type': "application/json",
'Authorization': "YOUR_SECRET_TOKEN"
}
conn.request("POST", "/configs/v1/authorization-policies", payload, headers)
res = conn.getresponse()
data = res.read()
Request to read the KBAC Policy configuration using REST.
{
"id": "your_policy_configuration_gid"
}Request to read the KBAC Policy configuration using Python.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
headers = { 'Authorization': "YOUR_SECRET_TOKEN" }
conn.request("GET", "/configs/v1/authorization-policies/{{id}}", headers=headers)
res = conn.getresponse()
data = res.read()
Step 3
Request to run a KBAC authZEN Evaluation - authorized.
{
"subject": {
"type": "Person",
"id": "knightrider"
},
"resource": {
"type": "Car",
"id": "kitt"
},
"action": {
"name": "CAN_DRIVE"
}
}Response to the KBAC authZEN Evaluation - authorized.
{
"decision": true
}Request to run a KBAC authZEN Evaluation - authorized.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = "{
"subject": {"type": "Person",
"id": "knightrider"},
"resource": {"type": "Car",
"id": "kitt"},
"action": {"name": "CAN_DRIVE"}
}"
headers = {
'Content-Type': "application/json",
'X-IK-ClientKey': ""
}
conn.request("POST", "/access/v1/evaluation", payload, headers)
res = conn.getresponse()
data = res.read()
Request to run a KBAC authZEN Evaluation - not authorized.
{
"subject": {
"type": "Person",
"id": "knightrider"
},
"resource": {
"type": "Car",
"id": "caddilacv16"
},
"action": {
"name": "CAN_DRIVE"
}
}Response to the KBAC authZEN Evaluation - not authorized.
{
"decision": false
}Step 4
Request to run a KBAC authZEN Action Search.
{
"subject": {
"type": "Person",
"id": "knightrider"
},
"resource": {
"type": "Car",
"id": "kitt"
}
}Response to the KBAC authZEN Action Search.
{
"results": [
{
"name": "CAN_DRIVE"
}
]
}Request to run a KBAC authZEN Action Search using Python.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = "{
"subject": {"type": "Person",
"id": "knightrider"},
"resource": {"type": "Car",
"id": "kitt"}
}"
headers = {
'Content-Type': "application/json",
'X-IK-ClientKey': ""
}
conn.request("POST", "/access/v1/search/action", payload, headers)
res = conn.getresponse()
data = res.read()
Request to run a KBAC authZEN Resource Search.
{
"subject": {
"type": "Person",
"id": "knightrider"
},
"resource": {
"type": "Car"
},
"action": {
"name": "CAN_DRIVE"
}
}Response to the KBAC authZEN Resource Search.
{
"results": [
{
"type": "Car",
"id": "kitt"
}
]
}Request to run a KBAC authZEN Resource Search using Python.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = "{
"subject": {"type": "Person",
"id": "knightrider"},
"resource": {"type": "Car"},
"action": {"name": "CAN_DRIVE"}
}"
headers = {
'Content-Type': "application/json",
'X-IK-ClientKey': ""
}
conn.request("POST", "/access/v1/search/resource", payload, headers)
res = conn.getresponse()
data = res.read()
Request to run a KBAC authZEN Subject Search.
{
"subject": {
"type": "Person"
},
"resource": {
"type": "Car",
"id": "kitt"
},
"action": {
"name": "CAN_DRIVE"
}
}Response to the KBAC authZEN Subject Search.
{
"results": [
{
"type": "Person",
"id": "knightrider"
}
]
}Request to run a KBAC authZEN Subject Search using Python.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = "{
"subject": {"type": "Person"},
"resource": {"type": "Car",
"id": "kitt"},
"action": {"name": "CAN_DRIVE"}
}"
headers = {
'Content-Type': "application/json",
'X-IK-ClientKey': ""
}
conn.request("POST", "/access/v1/search/subject", payload, headers)
res = conn.getresponse()
data = res.read()
Step 5
Delete the KBAC Policy.
{
"id": "your_policy_configuration_gid"
}Request to delete the KBAC Policy.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
headers = { 'Authorization': "Bearer ...", 'Content-Type': "application/json" }
conn.request("DELETE", "/configs/v1/authorization-policies/{id}", headers=headers)
res = conn.getresponse()
data = res.read()
API Endpoints
/capture/v1/nodes /capture/v1/relationships /configs/v1/authorization-policies /kbac/v1/is-authorized