Skip to content
TDACorpIDENTITYSign in

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 needUse
A fast check on every requestVerify the JWT locally. See Access token.
To react to revocation or an ended session sooner than the token expiresIntrospect, for example before a sensitive action, or on a short cache.
To check a refresh tokenIntrospect. 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.

ParameterRule
client_idRequired exactly once. Your client.
tokenRequired exactly once. The access token or refresh token.
Client authenticationThe 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#

MemberMeaning
activetrue
scopeSpace-separated scopes.
client_id, sub, iss, aud, jti, iat, expAs in the token.
nbfWhen present in the token.
token_typeDPoP when the token is key-bound, otherwise Bearer.
tid, tslug, sid, acr, amr, auth_time, av, pv, pvt, cnf, azp, act, kind, verCopied from the token when present. Each is defined in the claims reference.

Active refresh token#

MemberMeaning
activetrue
scope, client_id, sub, iss, iat, expAs for the token. exp is the end of its current sliding window.
token_typerefresh_token
sidThe session the token came from.
tidThe organization, when there is one.

Errors#

Only the request itself can fail.

StatuserrorWhen
400invalid_requestA wrong content type, oversized body, or token missing or repeated.
401invalid_clientclient_id missing, unknown or malformed, or authentication failed.
400use_dpop_nonce or invalid_dpop_proofYour client requires DPoP and the proof is missing a current nonce or is invalid. Retry once with the DPoP-Nonce header.
429Refused 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 aud and, 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: true is a window in which a revoked token still works. Never cache beyond the token's exp.
  • Protect your client credentials. Anyone who can authenticate as your client can ask about your tokens.

Verified against commit 7ff8932