KBAC: authZEN + advice.
Create a policy and run a KBAC query. An advice is answered if the user does not have enough authorization.
Use case
When a user requests access to their Profile resource, an authorization check should happen, which must check the
user's current authentication level against a minimum value. If the user's current authentication level is lesser than the level
required by the access policy, the KBAC engine should deny the action and also respond to the call with an Advice suggesting the
user should step-up their authentication level.
Create a policy which rules that a Person node can service a laptop if the Person node owns it and if the token of the Person node access Token
has not expired.

Requirements
- ServiceAccount credentials created in the IndyKite Hub for your organization.
- AppAgent credentials created in the IndyKite Hub, using the REST endpoints or using Terraform for your Project / Application.
- Auth0 user token for the user who requires access.
Steps
1. Using the AppAgent credential as API Key (name: X-IK-ClientKey), ingest data in your IKG (IndyKite Knowledge Graph) using the script provided.
2. Using the ServiceAccount credential as Bearer token, create a KBAC Policy.
3. Using the AppAgent credential as API Key (name: X-IK-ClientKey), run a KBAC authZEN Evaluation which returns step up.
4. Using the AppAgent credential as API Key (name: X-IK-ClientKey), run a KBAC authZEN Evaluation which gives access.
5. Delete your configuration.
6. Try with your own data.
Step 1
Ingest 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
}
]
}Ingest 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 service a laptop if the Person node owns it and if the external_id of the subject Person node is equal to the token sub.
{
"meta": {
"policy_version": "2.0-kbac"
},
"subject": {
"type": "Token"
},
"actions": [
"CAN_SERVICE"
],
"resource": {
"type": "Laptop"
},
"condition": {
"cypher": "MATCH (subject:Token)-[:_SAME_AS]->(person:Person)-[:OWNS]->(resource)",
"filter": {
"attribute": "$token.exp",
"operator": ">",
"value": 1773162816,
"advice": {
"error": "insufficient_user_authentication",
"error_description": "Authentication is expired",
"sub": "$token.exp"
}
}
}
}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\":\"Token\"},\"actions\":[\"CAN_SERVICE\"],\"resource\":{\"type\":\"Laptop\"},\"condition\":{\"cypher\":\"MATCH (subject:Token)-[:_SAME_AS]->(person:Person)-[:OWNS]->(resource)\",\"filter\":{\"attribute\":\"$token.exp\",\"operator\":\">\",\"value\":1773162816,\"advice\":{\"error\":\"insufficient_user_authentication\",\"error_description\":\"Authentication is expired\",\"sub\":\"$token.exp\"}}}}",
"status": "ACTIVE",
"tags": []
}Request to create the KBAC Policy configuration using REST.
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 REST.
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
Run a KBAC authZEN Evaluation which returns step up.
{
"subject": {
"type": "Token",
"id": "token_sub_value"
},
"resource": {
"type": "Laptop",
"id": "airbook-xyz"
},
"action": {
"name": "CAN_SERVICE"
}
}Request to run KBAC authZEN Evaluation which returns step up.
import http.client
conn = http.client.HTTPSConnection("eu.api.indykite.com")
payload = "{
"subject": {"type": "Token",
"id": "token_sub_value"},
"resource": {"type": "Laptop",
"id": "airbook-xyz"},
"action": {"name": "CAN_SERVICE"}
}"
headers = {
'Content-Type': "application/json",
'Authorization': "Bearer eyJh....",
'X-IK-ClientKey': "eyJh...."
}
conn.request("POST", "/access/v1/evaluation", payload, headers)
res = conn.getresponse()
data = res.read()
Response to the KBAC authZEN Evaluation request.
{
"context": {
"advice": [
{
"error": "insufficient_user_authentication",
"error_description": "Authentication is expired",
"sub": "$token.exp"
}
]
},
"decision": false
}Step 4
Add the Person node access token in the headers:
key:Authorization value: Bearer access_token_value
Then run the same KBAC authZEN Evaluation.
{
"subject": {
"type": "Token",
"id": "token_sub_value"
},
"resource": {
"type": "Laptop",
"id": "airbook-xyz"
},
"action": {
"name": "CAN_SERVICE"
}
}Response to the KBAC authZEN Evaluation request.
{
"decision": true
}Step 5
Delete the KBAC Policies.
{
"id": "your_policy_configuration_gid"
}Request to delete the KBAC Policies.
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()