Skip to main content

Ask for a decision with AuthZEN

Use POST /access/v1/evaluation when a service needs a yes or no answer about a subject, an action and a resource, and has no token for that subject. The request and response follow the AuthZEN access evaluation shape.

Give the caller the authzen scope​

The caller is a client with the authzen scope on the built-in type urn:as:authzen. This grants it to the orders-api client from Check a token at your resource server with introspection. The call replaces that client's entry, so it lists both grants.

curl -fsS -X PATCH "$POLICYARC_URL/admin/api/policy-data/by-key?dataKey=pbac.operator.controls.client_entitlements&path=client_id.$RS_CLIENT_ID" \
-H "X-Admin-API-Key: $POLICYARC_ADMIN_KEY" \
-H 'Content-Type: application/json' \
-d '{"grant_types": ["client_credentials"], "granted_resources": [{"type": "urn:as:introspect", "scopes": ["introspection"]}, {"type": "urn:as:authzen", "scopes": ["authzen"]}]}'

Ask​

The block first waits a few seconds for the policy engine to load the grant.

sleep 5
AUTHZEN_TOKEN=$(curl -fsS -u "$RS_CLIENT_ID:$RS_CLIENT_SECRET" "$POLICYARC_URL/token" \
-d grant_type=client_credentials -d scope=authzen -d resource_types=urn:as:authzen |
jq -er .access_token)

resp=$(curl -fsS "$POLICYARC_URL/access/v1/evaluation" \
-H "Authorization: Bearer $AUTHZEN_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"subject": {"type": "user", "id": "alice@example.com"},
"action": {"name": "orders:read"},
"resource": {"type": "urn:example:orders", "id": "42"}
}')
echo "$resp"
jq -e '.decision == true' <<<"$resp" >/dev/null || { echo 'Expected "decision": true' >&2; false; }

The answer is {"decision": true} or {"decision": false}. The check expects true, the shipped answer for a subject that is not on the denylist. subject, action and resource are required. context is optional.

Basic auth with the client's id and secret works too, in place of the bearer token. The admin key does not. A call with only X-Admin-API-Key gets HTTP 401 {"error":"invalid_client","error_description":"client_id or Bearer token is required"}.

What decides​

The endpoint runs the direct.test policy, not the token policy. As shipped, that policy denies a subject listed in the denylist control and allows every other request.

What we setDecision for alice@example.com
Nothingtrue
alice@example.com in pbac.operator.controls.denylistfalse
alice@example.com denied orders:read in pbac.operator.controls.subject_restrictionstrue

The subject restrictions control does not change AuthZEN answers today. The token policy reads that control, and direct.test does not. Do not rely on AuthZEN for a restriction you set there.

Each call writes an /access/v1/evaluation audit row with the subject id and the decision.