Back to all resources
KBAC KBAC Json

KBAC: Check a Permission Grid for One Subject with authZEN Evaluations (Boxcar)

Use the authZEN /access/v1/evaluations endpoint to check, in a single call, whether one subject is allowed across a grid of (resource, action) cells. The response returns one decision per cell, in order; the client keeps the cells whose decision is true.

KBAC: Check a Permission Grid for One Subject with authZEN Evaluations (Boxcar)

This example demonstrates the authZEN /access/v1/evaluations (boxcarring) endpoint to discover what one subject can do across several (resource, action) cells in a single round-trip.

Note: the older /access/v1/what-authorized endpoint is deprecated. Use /access/v1/evaluations (this example) for grid checks, or the search endpoints for type-level discovery.

How the evaluations endpoint works:

- Top-level subject / action / resource act as defaults.

- Each entry in the evaluations array can override any of them; missing fields inherit the defaults.

- The response is an evaluations array with one { decision: true|false } per request, in the same order.

How it relates to the search endpoints:

- /search/action - "for THIS subject + THIS resource, which actions are allowed?"

- /search/resource - "for THIS subject + THIS action, which resources are allowed?"

- /search/subject - "for THIS resource + THIS action, which subjects are allowed?"

- /evaluations - "for THIS subject, decide each of these concrete (resource, action) cells at once."

Use /evaluations when you already know the concrete resources to check. For type-level discovery ("which cars can the subject drive?") use /search/resource (see authz-1 and authz-4).

Use case

Scenario: A self-service portal renders a side menu. Each item maps to a concrete (resource, action) cell. Before rendering, the portal asks IndyKite which items are available to the signed-in user in one boxcar call.

Default subject: Karel

Candidate cells:

- (Car kitt, CAN_DRIVE)

- (Bus harmonika, CAN_RIDE)

- (Car kitt, CAN_WASH)

Policies in scope:

- Person can CAN_DRIVE a Car if a DRIVES relationship exists.

- Person can CAN_RIDE a Bus if they hold a Ticket for it (Person -HAS-> Ticket -FOR-> Bus).

- (No CAN_WASH policy defined.)

Karel holds a Ticket (listek) that is FOR the Harmonika bus, but does not drive kitt and no CAN_WASH policy applies. The evaluations response is therefore [false, true, false] - one decision per cell, in order.

Render only the menu item whose decision is true (CAN_RIDE the bus); leave the others hidden or grayed out.

ikg

Requirements

Prerequisites:

- ServiceAccount credentials: For creating the policies.

- AppAgent credentials: For calling /access/v1/evaluations (X-IK-ClientKey).

- Graph data including Person, Car, Bus, and Ticket nodes, with DRIVES relationships and a Person -HAS-> Ticket -FOR-> Bus path.

- At least one policy per (resource, action) cell you want to evaluate.

Required API access:

- POST /configs/v1/authorization-policies (one per action)

- POST /access/v1/evaluations

Steps

Step 1: Capture Graph Data

- Action: POST Person, Car, Bus, Ticket nodes; DRIVES relationships and the Person -HAS-> Ticket -FOR-> Bus path.

- Result: Karel -HAS-> Ticket(listek) -FOR-> Bus(harmonika); no DRIVES from Karel.

Step 2: Create Per-Action Policies

- Action: POST one policy for CAN_DRIVE on Car, one for CAN_RIDE on Bus. Leave CAN_WASH undefined intentionally.

- Result: Policy IDs returned.

Step 3: Call /access/v1/evaluations

- Authentication: AppAgent credential.

- Action: POST a default subject (Karel) plus an evaluations array of concrete (resource, action) cells.

- Result: An evaluations array with one decision per cell, in order. Keep the cells where decision is true.

Step 1

Capture nodes used in this example. Re-use the authZEN dataset.

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 DRIVES relationships plus the Person -HAS-> Ticket -FOR-> Bus path (karel HAS listek, listek FOR harmonika).

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

CAN_DRIVE policy (Person -[DRIVES]-> Car).

policy_drive.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 CAN_DRIVE policy.

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": []
}

CAN_RIDE policy (Person -HAS-> Ticket -FOR-> Bus).

policy_ride.jsonJson
{
  "meta": {
    "policy_version": "2.0-kbac"
  },
  "subject": {
    "type": "Person"
  },
  "actions": [
    "CAN_RIDE"
  ],
  "resource": {
    "type": "Bus"
  },
  "condition": {
    "cypher": "MATCH (subject:Person)-[:HAS]->(ticket:Ticket)-[:FOR]->(resource:Bus)"
  }
}

Request to create the CAN_RIDE policy.

POST https://eu.api.indykite.com/configs/v1/authorization-policiesJson
{
  "project_id": "your_project_gid",
  "description": "Authorize CAN_RIDE on Bus when the subject holds a Ticket for it (Person -HAS-> Ticket -FOR-> Bus).",
  "display_name": "policy - person can ride a bus",
  "name": "policy-person-can-ride-a-bus",
  "policy": "{\"meta\":{\"policy_version\":\"2.0-kbac\"},\"subject\":{\"type\":\"Person\"},\"actions\":[\"CAN_RIDE\"],\"resource\":{\"type\":\"Bus\"},\"condition\":{\"cypher\":\"MATCH (subject:Person)-[:HAS]->(ticket:Ticket)-[:FOR]->(resource:Bus)\"}}",
  "status": "ACTIVE",
  "tags": []
}

Step 3

Boxcar evaluations: a default subject (Karel) plus three concrete (resource, action) cells to decide at once.

POST https://eu.api.indykite.com/access/v1/evaluationsJson
{
  "subject": {
    "type": "Person",
    "id": "karel"
  },
  "evaluations": [
    {
      "resource": {
        "type": "Car",
        "id": "kitt"
      },
      "action": {
        "name": "CAN_DRIVE"
      }
    },
    {
      "resource": {
        "type": "Bus",
        "id": "harmonika"
      },
      "action": {
        "name": "CAN_RIDE"
      }
    },
    {
      "resource": {
        "type": "Car",
        "id": "kitt"
      },
      "action": {
        "name": "CAN_WASH"
      }
    }
  ]
}

Response - one decision per cell, in request order: [CAN_DRIVE kitt = false, CAN_RIDE harmonika = true, CAN_WASH kitt = false].

Response 200Json
{
  "evaluations": [
    {
      "decision": false
    },
    {
      "decision": true
    },
    {
      "decision": false
    }
  ]
}

Same call in Python.

evaluations.pyPython

import http.client
import json

conn = http.client.HTTPSConnection("eu.api.indykite.com")

payload = json.dumps({
  "subject": {"type": "Person", "id": "karel"},
  "evaluations": [
    {"resource": {"type": "Car", "id": "kitt"}, "action": {"name": "CAN_DRIVE"}},
    {"resource": {"type": "Bus", "id": "harmonika"}, "action": {"name": "CAN_RIDE"}},
    {"resource": {"type": "Car", "id": "kitt"}, "action": {"name": "CAN_WASH"}}
  ]
})

headers = {
  'Content-Type': "application/json",
  'X-IK-ClientKey': ""
}

conn.request("POST", "/access/v1/evaluations", payload, headers)

res = conn.getresponse()
data = res.read()