Back to all resources
KBAC KBAC Python

KBAC: Relationship-Based Authorization with authZEN API

Create a Knowledge-Based Access Control (KBAC) policy and execute authZEN-compliant authorization queries. This example demonstrates evaluation (can X do Y to Z?) and search operations (who can? what can? which resources?).

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.

ikg

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.

POST https://eu.api.indykite.com/capture/v1/nodes/Json
{
  "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.

POST https://eu.api.indykite.com/capture/v1/relationships/Json
{
  "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.

policy.jsonJson
{
  "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.

POST https://eu.api.indykite.com/configs/v1/authorization-policiesJson
{
  "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.

policy_request.pyPython

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.

GET https://eu.api.indykite.com/configs/v1/authorization-policies/{id}Json
{
  "id": "your_policy_configuration_gid"
}

Request to read the KBAC Policy configuration using Python.

policy_request.pyPython

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.

POST https://eu.api.indykite.com/access/v1/evaluationJson
{
  "subject": {
    "type": "Person",
    "id": "knightrider"
  },
  "resource": {
    "type": "Car",
    "id": "kitt"
  },
  "action": {
    "name": "CAN_DRIVE"
  }
}

Response to the KBAC authZEN Evaluation - authorized.

Response 200Json
{
  "decision": true
}

Request to run a KBAC authZEN Evaluation - authorized.

evaluation.pyPython

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.

POST https://eu.api.indykite.com/access/v1/evaluationJson
{
  "subject": {
    "type": "Person",
    "id": "knightrider"
  },
  "resource": {
    "type": "Car",
    "id": "caddilacv16"
  },
  "action": {
    "name": "CAN_DRIVE"
  }
}

Response to the KBAC authZEN Evaluation - not authorized.

Response 200Json
{
  "decision": false
}

Step 4

Request to run a KBAC authZEN Action Search.

POST https://eu.api.indykite.com/access/v1/search/actionJson
{
  "subject": {
    "type": "Person",
    "id": "knightrider"
  },
  "resource": {
    "type": "Car",
    "id": "kitt"
  }
}

Response to the KBAC authZEN Action Search.

Response 200Json
{
  "results": [
    {
      "name": "CAN_DRIVE"
    }
  ]
}

Request to run a KBAC authZEN Action Search using Python.

action.pyPython

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.

POST https://eu.api.indykite.com/access/v1/search/resourceJson
{
  "subject": {
    "type": "Person",
    "id": "knightrider"
  },
  "resource": {
    "type": "Car"
  },
  "action": {
    "name": "CAN_DRIVE"
  }
}

Response to the KBAC authZEN Resource Search.

Response 200Json
{
  "results": [
    {
      "type": "Car",
      "id": "kitt"
    }
  ]
}

Request to run a KBAC authZEN Resource Search using Python.

resource.pyPython

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.

POST https://eu.api.indykite.com/access/v1/search/subjectJson
{
  "subject": {
    "type": "Person"
  },
  "resource": {
    "type": "Car",
    "id": "kitt"
  },
  "action": {
    "name": "CAN_DRIVE"
  }
}

Response to the KBAC authZEN Subject Search.

Response 200Json
{
  "results": [
    {
      "type": "Person",
      "id": "knightrider"
    }
  ]
}

Request to run a KBAC authZEN Subject Search using Python.

subject.pyPython

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.

DELETE https://eu.api.indykite.com/configs/v1/authorization-policies/{id}Json
{
  "id": "your_policy_configuration_gid"
}

Request to delete the KBAC Policy.

del.pyPython

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
View OpenAPI docs

Tags

KBAC Policy authZEN Authorization Evaluation Action Search Resource Search Subject Search Access Control