KBAC: Parameterized Authorization with Input Params (max_price)
This example demonstrates input_params passed through context on authZEN requests.
Policy condition shape:
MATCH (subject) MATCH (resource)-[:HAS]->(price:Property {type:'price'})
WHERE price.value <= $max_price AND NOT (subject)-[:OWNS]->(resource)
Two things matter:
1. $max_price is a partial filter - its value is supplied per request via context.input_params.
2. The NOT clause excludes cars the subject already owns, which keeps the answer truthful for "what can I buy?" style questions.
authZEN endpoints exercised:
- POST /access/v1/evaluation - "Can Karel buy KITT under $150,000?" -> true. Same question under $5,000 -> false.
- POST /access/v1/search/resource - "Which cars can Knight Rider buy under $5,000?" -> [{skodaOctavia}].
- POST /access/v1/search/subject - "Who can buy the Skoda Octavia under $5,000?" -> [knightrider, karel].
Use case
Scenario: A used-car marketplace asks IndyKite "what can this shopper afford right now?" with a moving budget cap.
Graph data:
- Cars carry a HAS -> Property{type:'price'} relationship with the listing price.
- Subjects OWN the cars they already bought (excluded from CAN_BUY results).
Run the same policy three ways:
1. evaluation with max_price=150000 -> Karel can buy KITT.
2. evaluation with max_price=5000 -> Karel cannot buy KITT.
3. search/resource with max_price=5000 -> only cars under $5,000 come back.
Use this pattern whenever the authorization rule depends on a numeric threshold supplied by the caller - discounts, credit limits, rate-limit budgets, etc.

Requirements
Prerequisites:
- ServiceAccount credentials: For creating the policy.
- AppAgent credentials: For evaluations and searches (X-IK-ClientKey).
- Graph data: Person, Car, and Property{type:'price'} nodes with HAS relationships from each Car to its price Property. OWNS relationships for any cars already owned.
Required API access:
- POST /configs/v1/authorization-policies
- POST /access/v1/evaluation
- POST /access/v1/search/resource
- POST /access/v1/search/subject
Steps
Step 1: Capture Graph Data
- Action: POST Person, Car, Property nodes; HAS and OWNS relationships.
- Result: Cars priced, owners linked.
Step 2: Create the Parameterized Policy
- Action: POST a KBAC policy with $max_price in the condition cypher.
- Result: Policy ID.
Step 3: Evaluate with Different Budgets
- Action: POST /access/v1/evaluation with context.input_params.max_price set.
- Result: decision flips based on price vs. budget.
Step 4: Search for Affordable Resources
- Action: POST /access/v1/search/resource with max_price in context.
- Result: All cars under the budget that the subject doesn't already own.
Step 5: Reverse Search (Who Can Buy This?)
- Action: POST /access/v1/search/subject with max_price in context.
- Result: All Persons who could afford the resource and don't already own it.
Step 1
Capture Person and Car nodes. Each Car carries a price property (kitt 100000, caddilacv16 150000, skodaOctavia 4000) — captured as an integer so the policy can compare price.value <= $max_price.
{
"nodes": [
{
"external_id": "knightrider",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "knightrider@demo.com"
}
]
},
{
"external_id": "karel",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "karel@demo.com"
}
]
},
{
"external_id": "kitt",
"type": "Car",
"properties": [
{
"type": "manufacturer",
"value": "Pontiac"
},
{
"type": "model",
"value": "Firebird"
},
{
"type": "price",
"value": 100000
}
]
},
{
"external_id": "caddilacv16",
"type": "Car",
"properties": [
{
"type": "manufacturer",
"value": "Cadillac"
},
{
"type": "model",
"value": "V-16"
},
{
"type": "price",
"value": 150000
}
]
},
{
"external_id": "skodaOctavia",
"type": "Car",
"properties": [
{
"type": "manufacturer",
"value": "Skoda"
},
{
"type": "model",
"value": "Octavia"
},
{
"type": "price",
"value": 4000
}
]
}
]
}Capture relationships: knightrider OWNS kitt, which the policy's NOT (subject)-[:OWNS]->(resource) clause uses to exclude cars the subject already owns.
{
"relationships": [
{
"source": {
"external_id": "knightrider",
"type": "Person"
},
"target": {
"external_id": "kitt",
"type": "Car"
},
"type": "OWNS"
}
]
}Step 2
KBAC policy: CAN_BUY a Car if its price is <= $max_price and the subject does not already own it.
{
"meta": {
"policy_version": "2.0-kbac"
},
"subject": {
"type": "Person"
},
"actions": [
"CAN_BUY"
],
"resource": {
"type": "Car"
},
"condition": {
"cypher": "MATCH (subject) MATCH (resource)-[:HAS]->(price:Property {type:'price'}) WHERE price.value <= $max_price AND NOT (subject)-[:OWNS]->(resource)"
}
}Request to create the policy.
{
"project_id": "your_project_gid",
"description": "Authorize CAN_BUY on Car when its price <= input_params.max_price and the subject does not already own it.",
"display_name": "policy - person can buy car under max_price",
"name": "policy-person-can-buy-car-max-price",
"policy": "{\"meta\":{\"policy_version\":\"2.0-kbac\"},\"subject\":{\"type\":\"Person\"},\"actions\":[\"CAN_BUY\"],\"resource\":{\"type\":\"Car\"},\"condition\":{\"cypher\":\"MATCH (subject) MATCH (resource)-[:HAS]->(price:Property {type:'price'}) WHERE price.value <= $max_price AND NOT (subject)-[:OWNS]->(resource)\"}}",
"status": "ACTIVE",
"tags": []
}Step 3
Evaluation: Karel asks if he can buy KITT with budget 150,000. Decision: true.
{
"subject": {
"type": "Person",
"id": "karel"
},
"resource": {
"type": "Car",
"id": "kitt"
},
"action": {
"name": "CAN_BUY"
},
"context": {
"input_params": {
"max_price": 150000
}
}
}Response - authorized.
{
"decision": true
}Same call, budget dropped to 5,000. Decision: false.
{
"subject": {
"type": "Person",
"id": "karel"
},
"resource": {
"type": "Car",
"id": "kitt"
},
"action": {
"name": "CAN_BUY"
},
"context": {
"input_params": {
"max_price": 5000
}
}
}Response - denied because KITT's price exceeds 5,000.
{
"decision": false
}Step 4
Resource search: which cars can Knight Rider buy under 5,000?
{
"subject": {
"type": "Person",
"id": "knightrider"
},
"resource": {
"type": "Car"
},
"action": {
"name": "CAN_BUY"
},
"context": {
"input_params": {
"max_price": 5000
}
}
}Response - only the Skoda Octavia fits the budget.
{
"results": [
{
"type": "Car",
"id": "skodaOctavia"
}
]
}Same resource search in Python.
import http.client
import json
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = json.dumps({
"subject": {"type": "Person", "id": "knightrider"},
"resource": {"type": "Car"},
"action": {"name": "CAN_BUY"},
"context": {"input_params": {"max_price": 5000}}
})
headers = {
'Content-Type': "application/json",
'X-IK-ClientKey': ""
}
conn.request("POST", "/access/v1/search/resource", payload, headers)
res = conn.getresponse()
data = res.read()
Step 5
Subject search: who can buy the Skoda Octavia under 5,000?
{
"subject": {
"type": "Person"
},
"resource": {
"type": "Car",
"id": "skodaOctavia"
},
"action": {
"name": "CAN_BUY"
},
"context": {
"input_params": {
"max_price": 5000
}
}
}Response - Persons who can afford it and don't already own it.
{
"results": [
{
"type": "Person",
"id": "knightrider"
},
{
"type": "Person",
"id": "karel"
}
]
}API Endpoints
/configs/v1/authorization-policies /access/v1/evaluation /access/v1/search/resource /access/v1/search/subject