Back to all resources
ContX IQContX IQPython

ContX IQ: Resolve the Caller's IKG Subject with GET /contx-iq/v1/whoami

Ask IndyKite which IKG node an end-user token resolves to. GET /contx-iq/v1/whoami returns the subject type and external ID that Token Introspect derived from the bearer token - and nothing else - so a client can build subject-bound AuthZEN and CIQ requests without decoding the token itself.

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.

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

GET https://eu.api.indykite.com/contx-iq/v1/whoamiJson
{
  "type": "Person",
  "id": "alice@example.com"
}

Same call in Python. The two returned values are used as the AuthZEN subject.

whoami.pyPython

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.

Response 401Json
{
  "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.

POST https://eu.api.indykite.com/access/v1/evaluationJson
{
  "subject": {
    "type": "Person",
    "id": "alice@example.com"
  },
  "resource": {
    "type": "Car",
    "id": "kitt"
  },
  "action": {
    "name": "CAN_DRIVE"
  }
}