ContX IQ: Resolve the Caller's IKG Subject with GET /contx-iq/v1/whoami
This example demonstrates the whoami endpoint of the ContX IQ REST API.
Endpoint: GET /contx-iq/v1/whoami - no body, no parameters.
Headers:
- X-IK-ClientKey: AppAgent credential. The agent needs the ContXIQ API permission (the same one /contx-iq/v1/execute uses).
- Authorization: Bearer <user-access-token> - required. Without it the call fails with 401 "end-user token is required".
Response:
- type: the IKG node type the token subject was matched to (the ikg_node_type of the Token Introspect configuration that validated the token).
- id: the token's original subject - the sub claim, or the claim named by sub_claim in the Token Introspect configuration. It equals the node's external_id in the IKG.
Nothing else from the token is exposed: no issuer, expiry, or mapped claims. If the Token Introspect configuration had no IKG node type to match against, both fields come back as empty strings with status 200.
Why it matters:
- The pair (type, id) is exactly the subject IndyKite will use for this user in CIQ executions and AuthZEN decisions. Send it as subject.type / subject.id.
- On 3.0-kbac policies a bearer-token AuthZEN call whose subject differs from the token's subject is denied with 403 Forbidden; whoami removes the guesswork.
- Clients no longer need to parse the JWT or replicate the sub_claim configuration to know who they are acting as.
Use case
Scenario: A front end holds an OAuth access token issued by an external identity provider for alice@example.com and wants to render "what can I do?" using the AuthZEN search endpoints. It needs the subject.type and subject.id IndyKite associates with that token.
Flow:
1. The Token Introspect configuration maps tokens from the identity provider to Person nodes, matching sub to external_id.
2. The client calls GET /contx-iq/v1/whoami with its AppAgent credential and the user's bearer token.
3. IndyKite answers {"type": "Person", "id": "alice@example.com"}.
4. The client sends that pair as the subject of /access/v1/search/resource (or any other AuthZEN or CIQ request) for the same user.
Also useful for:
- Debugging Token Introspect: a whoami call shows immediately whether the sub_claim and ikg_node_type settings produce the node you expect.
- Multi-IdP setups: the same client code works whatever claim each configuration uses as the subject.
Requirements
Prerequisites:
- ServiceAccount credentials: For creating the Token Introspect configuration.
- AppAgent credentials with the ContXIQ API permission: For calling /contx-iq/v1/whoami (X-IK-ClientKey).
- A user access token issued by the identity provider the Token Introspect configuration trusts (issuer and audience must match).
Required API access:
- POST /configs/v1/token-introspects
- GET /contx-iq/v1/whoami
Steps
Step 1: Configure Token Introspect
- Authentication: ServiceAccount credential as Bearer token.
- Action: POST /configs/v1/token-introspects with ikg_node_type "Person" and a jwt_matcher for your identity provider. With perform_upsert true the Person node is created on first use.
- Result: Tokens from that issuer now resolve to Person nodes whose external_id is the token's sub claim.
Step 2: Ask who the token is
- Authentication: AppAgent credential (X-IK-ClientKey) plus the user's token (Authorization: Bearer).
- Action: GET /contx-iq/v1/whoami.
- Result: {"type": "Person", "id": "alice@example.com"}.
Step 3: See the failure without a user token
- Action: Repeat the call with only X-IK-ClientKey.
- Result: 401 {"message": "end-user token is required"}.
Step 4: Reuse the answer as the AuthZEN subject
- Action: Put type and id into subject.type / subject.id of an evaluation or search request, sent with the same bearer token.
- Result: The decision is made for the very node the token resolves to.
Step 1
Token Introspect configuration: tokens from the trusted issuer are matched to Person nodes by their sub claim (external_id). The response type of whoami comes from ikg_node_type; its id from the subject claim.
{
"claims_mapping": {
"email": {
"selector": "email"
},
"name": {
"selector": "full_name"
}
},
"description": "Token introspect description",
"display_name": "Token introspect name",
"ikg_node_type": "Person",
"jwt_matcher": {
"audience": "audience-id",
"issuer": "https://example.com"
},
"name": "rest-token-introspect",
"online_validation": {
"cache_ttl": 600
},
"perform_upsert": true,
"project_id": "gid-of-project"
}Step 2
whoami: no body, no parameters. Send X-IK-ClientKey (AppAgent credential) and Authorization: Bearer <user-access-token>. The response is shown.
{
"type": "Person",
"id": "alice@example.com"
}Same call in Python. The two returned values are used as the AuthZEN subject.
import http.client
import json
conn = http.client.HTTPSConnection("eu.api.indykite.com")
headers = {
'X-IK-ClientKey': "",
'Authorization': "Bearer <user-access-token>"
}
conn.request("GET", "/contx-iq/v1/whoami", headers=headers)
res = conn.getresponse()
me = json.loads(res.read())
# me == {"type": "Person", "id": "alice@example.com"}
subject = {"type": me["type"], "id": me["id"]}
Step 3
Without the Authorization: Bearer header the endpoint refuses the call: there is no _Application form of whoami.
{
"message": "end-user token is required"
}Step 4
The whoami answer plugged into an AuthZEN evaluation for the same user. Send it with the same bearer token; on 3.0-kbac policies the subject must equal the token's subject or the call is denied with 403.
{
"subject": {
"type": "Person",
"id": "alice@example.com"
},
"resource": {
"type": "Car",
"id": "kitt"
},
"action": {
"name": "CAN_DRIVE"
}
}