Keycloak’s token introspection endpoint is your secret weapon for verifying if a token is still valid and what claims it holds, all without needing to parse the token itself on your client.
Let’s see it in action. Imagine you have a client application that receives a JWT access token from Keycloak. Instead of decoding the JWT locally to check its expiry or scope, you can send that token to Keycloak’s introspection endpoint.
Here’s a typical request you’d make from your backend service to Keycloak:
curl -X POST \
https://your-keycloak-domain.com/auth/realms/your-realm/protocol/openid-connect/token/introspect \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI..." \
-u "your-client-id:your-client-secret"
The -d "token=..." part is the JWT you want to validate. The -u "your-client-id:your-client-secret" is how your client application authenticates itself to Keycloak to be allowed to introspect tokens. This is crucial – only clients with the introspection client authentication flow enabled can use this endpoint.
Keycloak responds with a JSON object. If the token is valid, you’ll get something like this:
{
"active": true,
"exp": 1678886400,
"iat": 1678882800,
"jti": "some-unique-id",
"iss": "https://your-keycloak-domain.com/auth/realms/your-realm",
"aud": "your-client-id",
"sub": "a-user-id",
"typ": "Bearer",
"azp": "your-client-id",
"session_state": "some-session-id",
"scope": "openid profile email",
"client_id": "your-client-id",
"username": "testuser"
}
The active: true is the primary indicator of validity. The exp field shows the expiration timestamp (Unix epoch time), iat the issued at time, sub the subject (usually the user ID), and scope lists the granted scopes. If the token has been revoked, or if it’s expired, or if it’s not a valid token for this realm, active will be false.
This endpoint is fundamental for securing your APIs. It allows your backend services to act as Resource Servers, verifying that incoming requests carry a legitimate and currently usable access token issued by your Keycloak Authorization Server. This completely offloads the cryptographic verification and claim extraction from your API clients, centralizing the security logic within Keycloak itself.
The magic behind this is that Keycloak maintains the state of all issued tokens – their validity, expiry, and associated claims. When you introspect a token, Keycloak doesn’t need to re-decode the JWT; it simply checks its internal state for that specific token ID (jti). This is significantly more efficient and secure than clients having to manage public keys or secret keys for JWT verification. Keycloak handles the cryptographic operations and token lifecycle management, providing a single source of truth for token validity.
A common misconception is that introspection is just a fancy way to decode a JWT. It’s not. While the response includes claims, the primary purpose is to get a definitive active: true/false status from the token issuer. You are querying Keycloak’s authoritative state, not just performing local JWT validation. This is crucial when dealing with token revocation, for example. A JWT might appear valid cryptographically, but Keycloak can mark it as inactive if it’s been explicitly revoked.
The client_credentials grant type is often used by backend services to obtain tokens that they can then introspect. However, the introspection endpoint itself requires the client that is performing the introspection to authenticate. This means the client ID and secret used in the -u flag must belong to a client configured in Keycloak that has the "introspection" capability. If this client is not properly configured or if its credentials are wrong, you’ll get an authentication error from Keycloak before it even looks at the token you’re trying to introspect.
If you’re struggling with introspection failing, the first thing to check is if the client performing the introspection request has the correct client_id and client_secret and if that client has been granted the introspection role within the Keycloak realm. You can verify this in the Keycloak Admin Console under your client’s "Roles" tab or "Advanced" settings.
The next hurdle you’ll likely encounter is understanding how to manage token revocation effectively using the introspection endpoint.