Token introspection is the process through which a resource server validates an access or refresh token by querying the authorization server, typically via an introspection endpoint.
This yields metadata (claims) about the token—such as subject (sub), scopes, issuer, and expiration.
Standardized by OAuth 2.0 Token Introspection (RFC 7662), introspection is critical for validating opaque tokens and can also play a role in managing JWTs across distributed systems.
Token Types & Validation Methods
1. Opaque Tokens
- Represented as random strings with no readable structure.
- Must be validated online via
/introspector/userinfoendpoints.
- Commonly issued by providers like Okta, Auth0, Keycloak.
- Enable centralized revocation and token lifecycle management.
Flow:
- Client sends the token to a resource server.
- The resource server sends a POST request to the introspection endpoint:
POST /introspect Authorization: Basic base64(client_id:client_secret) Content-Type: application/x-www-form-urlencoded token=ACCESS_TOKEN
- The authorization server returns JSON describing the token:
{ "active": true, "scope": "read write", "client_id": "client123", "username": "alice", "sub": "user123", ... }
- The resource server uses the returned claims for authorization and access control decisions.
2. JWT Tokens (JSON Web Tokens)
- Self-contained, signed tokens that include structured claims.
- Can be validated offline, without contacting the issuer, by:
- Decoding the payload.
- Verifying the signature using a public key (via JWKS or
.well-known).
- Use introspection optionally for:
- Claim enrichment.
- Additional validation logic or identity mapping.
Flow:
- Receives the JWT (e.g., via
Authorization: Bearer ...header).
- Decodes the token (Base64) to inspect claims.
- Verifies the signature using:
- A public key (RS256) from the issuer's JWKS endpoint.
- Or a shared secret (HS256).
- Uses verified claims (
sub,exp,scope,aud, etc.) to enforce access policies.
Introspection endpoints are not necessary for JWTs when the token can be fully validated offline.
IndyKite-Specific Token Handling
IndyKite APIs can identify users via third-party tokens through token introspection configuration. This configuration enables the IndyKite platform to validate these tokens and utilize their content. Therefore, you must create a configuration that outlines how this token introspection should occur.
Process: Token Exchange with 3rd-Party JWTs
Step 1: Validation
This process involves examining the iss (issuer) claim within the JWT.
If the token is issued by IndyKite, standard introspection procedures apply.
Otherwise, the configuration must be fetched to perform the necessary checks.
The configuration will contain the type of verification:
- JWT (Offline): Validate using public keys or
.well-known/jwks.json.
Terraform example:
resource "indykite_token_introspect" "token_config" {
name = "terraform-token-introspect"
display_name = "Terraform token introspect"
description = "Token introspect for User access token"
location = "ProjectGID"
jwt_matcher { -> JWT specifies all attributes to match with received token.
issuer = "https://xx.xx.auth0.com/" -> Issuer is used to exact match based on iss claim in JWT.
audience = "client-id" -> Audience is used to exact match based on aud claim in JWT
}
offline_validation {} -> Offline validation works only with JWT. If public_jwks is empty, will be generated
ikg_node_type = "Person" -> Node type in IKG to which we will try to match sub claim with DT external_id.
claims_mapping = { -> ClaimsMapping specifies which claims from the token should be mapped to IKG Property with given name.
"email" = "email"
"phone_number" = "phone_number"
}
perform_upsert = true -> Perform Upsert specify, if we should create and/or update Identity node in IKG if it doesn't exist with.
}
- Opaque (Online): Use
/userinfoor introspection endpoints.
Terraform example:
resource "indykite_token_introspect" "token_config" {
name = "terraform-token-introspect"
display_name = "Terraform token introspect"
description = "Token introspect for User access token"
location = "ProjectGID"
opaque_matcher { -> Opaque specifies the configuration is for opaque tokens.
hint = "my.domain.com"
}
online_validation {
user_info_endpoint = "https://example.com/userinfo" -> URI of userinfo endpoint which will be used to validate access token and also fetch user claims when opaque token is received. It can remain empty, if JWT token matcher is used
cache_ttl = 600 -> Cache TTL of token validity can be used to minimize calls to userinfo endpoint. If not set, token will not be cached and call to userinfo endpoint will be made on every request
}
ikg_node_type = "Person" -> Node type in IKG to which we will try to match sub claim with identity node external_id.
claims_mapping = { -> ClaimsMapping specifies which claims from the token should be mapped to IKG Property with given name.
"email" = "email"
"phone_number" = "phone_number"
}
perform_upsert = true -> Perform Upsert specify, if we should create and/or update Identity node in IKG if it doesn't exist with.
}
Step 2: Subject Mapping
When the validity of the token and data are known from previous step, we can start with matching the IndyKite sub based on received sub from the 3rd party IDP.
To properly do this matching, we need to know:
- Usually,
subclaim from 3rd party IDP that is equal toexternal_idin IKG. (Therefore, you should never useexternal_idas a claims_mapping key).You can also use a different claim to identify the subject.
typethat is part of configurationexternal_idis not unique within whole IKG, but only pertype. To uniquely find an identity node, we need to know its type too.
Based on that, we will know all the data to populate IndyKite token claims.
Step 3: Claims Mapping
The claims_mapping attribute specifies which claims from the token should be mapped to new names and name of property in IKG. Be aware, that this can override any existing claims, which might not be accessible anymore by internal services.
Key specifies the new name and also the name of the property in IKG.
It must follow: max_len: 256 and pattern: "^[a-zA-Z_][a-zA-Z0-9_]+$"
Value specifies which Token claim to map and how.
By default we support all standard claims from OpenID specification https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims and mapping will fail if claim and data type do not match the standard.
For non-standard claims the type will be derived from the JSON.
Step 4: Token Exchange and Optional Upsert
Optionally supports Just-In-Time (JIT) provisioning: upsert the corresponding identity node in the IKG based on claims (perform_upsert attribute set to true).
JIT provisioning refers to the on-demand creation of a user identity node in the IKG when the user accesses the system for the first time, using the identity attributes from the token.
The user is granted access immediately, based on their new local identity.
Be aware that for performance reasons, if the created identity node is deleted, the token introspect will not create a new node if called again with the same token. A new token will need to be generated.
Configuration & Integration Options
| Option | JWT | Opaque |
|---|---|---|
| Issuer | ✅ Required | ❌ |
| Audience (client_id) | ✅ Required | ❌ |
| Public Key (JWKS) | ✅ Used for signature verification | ❌ |
| User Info / Introspect Endpoint | Optional for Offline / ✅ Required for Online | ✅ Required |
| Caching | ✅ JWKS & claims caching | ✅ Token metadata caching |
| Validation Method | Offline/Online | Online |
Common Claims in Introspection & JWTs
| Claim | Description |
|---|---|
sub |
Subject (user ID) of the token. |
username |
Login name of the user. |
email |
Email of the user. |
client_id |
OAuth client that obtained the token. |
exp, iat |
Expiration and issued-at timestamps. |
scope |
Space-separated list of access scopes. |
aud |
Intended audience(s). |
iss |
Issuer of the token. |
jti |
Unique token identifier. |
roles, permissions |
Optional claims for access control. |
acr |
If acr Claim requested as Essential with values parameter requesting specific Authentication Context Class Reference values, the Authorization Server MUST return an acr Claim Value that matches one of the requested values. |
Feature Summary
| Feature | Supported |
|---|---|
| JWT introspection | ✅ |
| Opaque token introspection | ✅ (Online) |
| Third-party token exchange | ✅ |
| Public key & metadata caching | ✅ |
| Multi-IDP support | ✅ |
| Claims mapping | ✅ Configurable |
| Just-In-Time provisioning (node upsert into IKG) | ✅ Optional |