Back to all resources
KBAC KBAC Python

KBAC: Parameterized Authorization with Input Params (max_price)

Drive authZEN evaluation and resource-search decisions using runtime input_params. The policy condition compares a graph property against $max_price provided at execution time, so the same policy answers different shopping-budget questions per call.

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.

ikg

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.

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

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

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

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

POST https://eu.api.indykite.com/access/v1/evaluationJson
{
  "subject": {
    "type": "Person",
    "id": "karel"
  },
  "resource": {
    "type": "Car",
    "id": "kitt"
  },
  "action": {
    "name": "CAN_BUY"
  },
  "context": {
    "input_params": {
      "max_price": 150000
    }
  }
}

Response - authorized.

Response 200Json
{
  "decision": true
}

Same call, budget dropped to 5,000. Decision: false.

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

Response 200Json
{
  "decision": false
}

Step 4

Resource search: which cars can Knight Rider buy under 5,000?

POST https://eu.api.indykite.com/access/v1/search/resourceJson
{
  "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.

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

Same resource search in Python.

search_resource.pyPython

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?

POST https://eu.api.indykite.com/access/v1/search/subjectJson
{
  "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.

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