Introspection
Ask identity whether an access token or refresh token is still active right now, and what it tells you.
On this page
Introspection (RFC 7662) answers one question: is this token usable at this moment? An access token is a signed JWT, so your API can check the signature and the expiry without calling identity. That cannot see a revocation, an ended session or a deactivated person. Introspection can.
When to use it#
| You need | Use |
|---|---|
| A fast check on every request | Verify the JWT locally. See Access token. |
| To react to revocation or an ended session sooner than the token expires | Introspect, for example before a sensitive action, or on a short cache. |
| To check a refresh token | Introspect. A refresh token is opaque, so there is nothing to verify locally. |
Request#
POST to the introspection_endpoint from discovery, which is /introspect, as application/x-www-form-urlencoded.
| Parameter | Rule |
|---|---|
client_id | Required exactly once. Your client. |
token | Required exactly once. The access token or refresh token. |
| Client authentication | The same as the token endpoint: a client assertion, plus a DPoP proof if your client requires one. |
token_type_hint is not needed and is ignored: identity recognises a refresh token by its form.
Who may ask about which token#
Identity answers about a token only for a caller entitled to know. An access token is visible to the client it was issued to and to the client that owns the resource its aud names. A refresh token is visible only to the client it was issued to. For any other caller the answer is {"active": false}, the same as for a token that does not exist.
Response#
Always 200 with Cache-Control: no-store once the caller is authenticated.
Inactive#
{ "active": false }A token is inactive when it is unknown, malformed, signed by a key identity does not publish, not an access token, expired, revoked, from a session that has ended, for a person or organization that is no longer active, issued to a client that is now suspended or can no longer enter the token's organization (its app is no longer installed there), for an organization that requires single sign-on whose session no longer holds a fresh single sign-on login (the sso_enforcement flag, default OFF), or one you are not entitled to see. Identity does not say which.
Active access token#
| Member | Meaning |
|---|---|
active | true |
scope | Space-separated scopes. |
client_id, sub, iss, aud, jti, iat, exp | As in the token. |
nbf | When present in the token. |
token_type | DPoP when the token is key-bound, otherwise Bearer. |
tid, tslug, sid, acr, amr, auth_time, av, pv, pvt, cnf, azp, act, kind, ver | Copied from the token when present. Each is defined in the claims reference. |
Active refresh token#
| Member | Meaning |
|---|---|
active | true |
scope, client_id, sub, iss, iat, exp | As for the token. exp is the end of its current sliding window. |
token_type | refresh_token |
sid | The session the token came from. |
tid | The organization, when there is one. |
Errors#
Only the request itself can fail.
| Status | error | When |
|---|---|---|
400 | invalid_request | A wrong content type, oversized body, or token missing or repeated. |
401 | invalid_client | client_id missing, unknown or malformed, or authentication failed. |
400 | use_dpop_nonce or invalid_dpop_proof | Your client requires DPoP and the proof is missing a current nonce or is invalid. Retry once with the DPoP-Nonce header. |
429 | Refused for too many requests. Honour Retry-After. |
Worked example#
curl -s https://identity.tdacorp.in/introspect \ --data-urlencode 'client_id=tdaid_c_example' \ --data-urlencode "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ --data-urlencode "client_assertion=$ASSERTION" \ --data-urlencode "token=$ACCESS_TOKEN"{ "active": true, "scope": "openid profile", "client_id": "tdaid_c_example", "sub": "0194f2b6-7c1e-7a30-9d4e-2f6f0f3b8c11", "iss": "https://identity.tdacorp.in", "aud": "https://api.example.com", "jti": "kq3T0u1mZb0Yx2yV7h1m6Q", "iat": 1790000000, "exp": 1790000600, "token_type": "DPoP", "sid": "0194f2b6-0000-7000-8000-000000000001", "acr": "aal2", "amr": ["hwk", "user"], "cnf": { "jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I" }, "kind": "human", "ver": 2}The values are illustrative.
Security notes#
- Introspection does not replace verification. Check
audand, for a DPoP token, the proof on the request you received. A token that introspects as active may still be addressed to another API. - Fail closed. If the call fails, do not treat the token as active.
- Cache briefly or not at all. A cached
active: trueis a window in which a revoked token still works. Never cache beyond the token'sexp. - Protect your client credentials. Anyone who can authenticate as your client can ask about your tokens.