Token revocation & introspection endpoints
As part of token management, Identify provides the ability to access the token revocation (RFC 7009) and introspection (RFC 7662) endpoints. In this document, we will guide you through the steps to effectively utilize these features for enhanced security and control over your tokens.
Discovery metadata
You can check the OpenID Connect Discovery endpoint of your Identify instance to see if the revocation_endpoint
endpoint and the introspection_endpoint
endpoint have been supported:
"introspection_endpoint": "https://dev.safewhere.local/runtime/oauth2/introspect.idp",
"revocation_endpoint": "https://dev.safewhere.local/runtime/oauth2/revoke.idp",
"token_endpoint_auth_methods_supported": [
"none",
"client_secret_basic",
"client_secret_post",
"private_key_jwt",
"tls_client_auth",
"self_signed_tls_client_auth"
],
"introspection_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post",
"private_key_jwt"
"tls_client_auth",
"self_signed_tls_client_auth"
],
"revocation_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post",
"private_key_jwt"
"tls_client_auth",
"self_signed_tls_client_auth"
]
Enable the token revocation & introspection endpoints
However, by default, these features are not available for tokens processed by all OAuth/OIDC connections. To enable this functionality, you must activate the Allow token revocation and introspection
setting on the Security tab of the respective connection:
Token revocation endpoint
Clients can notify the Identify OAuth server that a previously acquired refresh or access token is no longer needed. This is done through a request to the token revocation endpoint, as outlined in RFC 7009.
The server will invalidate the specified token. If it is a refresh token, it cannot be used to exchange for new tokens.
Token revocation request
It is specified in the server metadata under the revocation_endpoint
and takes on this format:
Request URL:
https://#yourdomain/runtime/oauth2/revoke.idp
Request body:
Parameter | Description |
---|---|
token | The token to revoke (required) |
token_type_hint | The type of the submitted token (optional). If omitted, the server will use heuristics to determine the token type: access_token or refresh_token |
client_secret_post method
When a client application sends a revocation request, it includes the client ID and the client secret in the request body.
POST /runtime/oauth2/revoke.idp //Line breaks for clarity
Host: identify01.identify.safewhere.com
Content-Type: application/x-www-form-urlencoded
client_id=oauth2_demo_clientid
&client_secret=oauth2_demo_clientsecret
&token_type_hint=refresh_token&token=CfDJ8JxLyFUJcjVHpbV1Rd6iCPLINbsdb4lqwB7vd284lsjVuunt9EpQY2zhnyDUQtzkGWtwJXcl1K-42eFkdccJQG-Y5j_-5zL5aRxC8B6bhmOMxNOzEsJApAdD2uPEaTb5ZXNQTvi73ACnpcCoSJSmf1_...Dllrx0D6aVCKlALTduWWxl2xgmCITJk5gLAjWVo_RYIyHjATOJgvUTfsO7zdt_N5nEWmPnwSNMYnhKCP3dGT5P2Cmp6zZG-F9ZBRlp3NseL4NP_9HDE-NDXqcERAhcsJ9NVZpHp_d7
client_secret_basic method
A client application builds a string by concatenating a client ID, a colon, and a client secret.
{client_id}:{client_secret}
Next, it needs to base64-encode the string and put it in the Authorization header of a revocation request.
POST /runtime/oauth2/revoke.idp //Line breaks for clarity
Host: identify01.identify.safewhere.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic b2F1dGgyX2RlbW9fY2xpZW50aWQ6b2F1dGgyX2RlbW9fY2xpZW50c2VjcmV0
token_type_hint=refresh_token
&token=CfDJ8JxLyFUJcjVHpbV1Rd6iCPLINbsdb4lqwB7vd284lsjVuunt9EpQY2zhnyDUQtzkGWtwJXcl1K-42eFkdccJQG-Y5j_-5zL5aRxC8B6bhmOMxNOzEsJApAdD2uPEaTb5ZXNQTvi73ACnpcCoSJSmf1_...Dllrx0D6aVCKlALTduWWxl2xgmCITJk5gLAjWVo_RYIyHjATOJgvUTfsO7zdt_N5nEWmPnwSNMYnhKCP3dGT5P2Cmp6zZG-F9ZBRlp3NseL4NP_9HDE-NDXqcERAhcsJ9NVZpHp_d7
private_key_jwt method
Identify allows you to use the private_key_jwt
method to authenticate your clients for the revocation endpoint, in the same way as for the token endpoint.
POST /runtime/oauth2/revoke.idp //Line breaks for clarity
Host: identify01.identify.safewhere.com
Content-Type: application/x-www-form-urlencoded
token_type_hint=refresh_token
&token=CfDJ8JxLyFUJcjVHpbV1Rd6iCPLINbsdb4lqwB7vd284lsjVuunt9EpQY2zhnyDUQtzkGWtwJXcl1K-42eFkdccJQG-Y5j_-5zL5aRxC8B6bhmOMxNOzEsJApAdD2uPEaTb5ZXNQTvi73ACnpcCoSJSmf1_...Dllrx0D6aVCKlALTduWWxl2xgmCITJk5gLAjWVo_RYIyHjATOJgvUTfsO7zdt_N5nEWmPnwSNMYnhKCP3dGT5P2Cmp6zZG-F9ZBRlp3NseL4NP_9HDE-NDXqcERAhcsJ9NVZpHp_d7
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IlBCX1hOYVFEWGp0NDB6UkUzbE1udzVPcUtDNCIsIng1dCI6IlBCX1hOYVFEWGp0NDB6UkUzbE1udzVPcUtDNCIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJvaWRjLWNsaWVudGlkIiwic3ViIjoib2lkYy1jbGllbnRpZCIsImF1ZCI6Imh0dHBzOi8vaWRlbnRpZnkwMS5pZGVudGlmeS5zYWZld2hlcmUuY29tL3J1bnRpbWUvb2F1dGgyL3Rva2VuLmlkcCIsImp0aSI6ImE3Y2Q3YzM3LWJlNmMtNDBmMy04MzhjLTNmYjMwYjg0OGFjMyIsImV4cCI6MjAzMjgyNTM5OCwibmJmIjoxNzE2MjkyNTk4LCJpYXQiOjE3MTYyOTI1OTh9.H0V8fgZOp_Ys2j_QxDF73I_i3L4blqlxWuQfEt8ZEh6ZTl8q5tpO_MarHE5yYGj_HW9U_keuaMzTabWXoIpLTzvN9gTPiQoLiP1meLKExgvQkiSMRyXEqENF7PWvWdTql7E5rna2To4ke_n0jnDze1RG82LajTfIP4K0opbup8bAY66PoOLiQlM82ZT2-UcxCRHP_EaMUGNSp06sFTtnkAI-3dOzOffhzOvFW0mUhCkdM1KLVOzuPX28PPlC6kPLDTPI3Xik3wszNtLLKGOdXTtfy3MDm9cUsJoKwh8LgpAim3tcaixYkujwy6XSsAy3IW2Q_BMfi6Mlj-R-DEb6Tw
Token revocation response
The possible responses are:
HTTP Status | Description |
---|---|
200 | The server will always return a 200 status code, regardless of the validity of the submitted token according to the specification. |
400 | Invalid or malformed request. |
401 | The request was denied due to invalid or missing client authentication. |
Successful response example
{}
Error response example
- 400 Bad Request:
{
"error": "invalid_request",
"error_description": "Invalid client assertion type."
}
- 401 Unauthorized:
{
"error": "invalid_client",
"error_description": "Client assertion is invalid due to missing required jti claim."
}
Token introspection endpoint
The Identify OAuth server's token introspection endpoint, as defined in RFC 7662, serves as the location where tokens undergo validation. These tokens are characterized by their extended expiration and serve as references to authorizations stored within the server.
Token introspection request
It is specified in the server metadata under the introspection_endpoint
and takes on this format:
Request URL:
https://#yourdomain/runtime/oauth2/introspect.idp
Request body:
Parameter | Description |
---|---|
token | The token to introspect (required) |
token_type_hint | The type of the submitted token (optional). If omitted, the server will use heuristics to determine the token type: access_token or refresh_token |
client_secret_post method
When a client application sends an introspection request, it includes the client ID and the client secret in the request body.
POST /runtime/oauth2/introspect.idp //Line breaks for clarity
Host: identify01.identify.safewhere.com
Content-Type: application/x-www-form-urlencoded
client_id=oauth2_demo_clientid
&client_secret=oauth2_demo_clientsecret
&token_type_hint=refresh_token
&token=CfDJ8JxLyFUJcjVHpbV1Rd6iCPLINbsdb4lqwB7vd284lsjVuunt9EpQY2zhnyDUQtzkGWtwJXcl1K-42eFkdccJQG-Y5j_-5zL5aRxC8B6bhmOMxNOzEsJApAdD2uPEaTb5ZXNQTvi73ACnpcCoSJSmf1_...Dllrx0D6aVCKlALTduWWxl2xgmCITJk5gLAjWVo_RYIyHjATOJgvUTfsO7zdt_N5nEWmPnwSNMYnhKCP3dGT5P2Cmp6zZG-F9ZBRlp3NseL4NP_9HDE-NDXqcERAhcsJ9NVZpHp_d7
client_secret_basic method
A client application builds a string by concatenating a client ID, a colon, and a client secret.
{client_id}:{client_secret}
Next, it needs to base64-encode the string and put it in the Authorization header of an introspection request.
POST /runtime/oauth2/introspect.idp //Line breaks for clarity
Host: identify01.identify.safewhere.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic b2F1dGgyX2RlbW9fY2xpZW50aWQ6b2F1dGgyX2RlbW9fY2xpZW50c2VjcmV0
token_type_hint=refresh_token
&token=CfDJ8JxLyFUJcjVHpbV1Rd6iCPLINbsdb4lqwB7vd284lsjVuunt9EpQY2zhnyDUQtzkGWtwJXcl1K-42eFkdccJQG-Y5j_-5zL5aRxC8B6bhmOMxNOzEsJApAdD2uPEaTb5ZXNQTvi73ACnpcCoSJSmf1_...Dllrx0D6aVCKlALTduWWxl2xgmCITJk5gLAjWVo_RYIyHjATOJgvUTfsO7zdt_N5nEWmPnwSNMYnhKCP3dGT5P2Cmp6zZG-F9ZBRlp3NseL4NP_9HDE-NDXqcERAhcsJ9NVZpHp_d7
private_key_jwt method
Identify allows you to use the private_key_jwt
method to authenticate your clients for the introspection endpoint, in the same way as for the token endpoint.
POST /runtime/oauth2/introspect.idp //Line breaks for clarity
Host: identify01.identify.safewhere.com
Content-Type: application/x-www-form-urlencoded
token_type_hint=refresh_token
&token=CfDJ8JxLyFUJcjVHpbV1Rd6iCPLINbsdb4lqwB7vd284lsjVuunt9EpQY2zhnyDUQtzkGWtwJXcl1K-42eFkdccJQG-Y5j_-5zL5aRxC8B6bhmOMxNOzEsJApAdD2uPEaTb5ZXNQTvi73ACnpcCoSJSmf1_...Dllrx0D6aVCKlALTduWWxl2xgmCITJk5gLAjWVo_RYIyHjATOJgvUTfsO7zdt_N5nEWmPnwSNMYnhKCP3dGT5P2Cmp6zZG-F9ZBRlp3NseL4NP_9HDE-NDXqcERAhcsJ9NVZpHp_d7
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IlBCX1hOYVFEWGp0NDB6UkUzbE1udzVPcUtDNCIsIng1dCI6IlBCX1hOYVFEWGp0NDB6UkUzbE1udzVPcUtDNCIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJvaWRjLWNsaWVudGlkIiwic3ViIjoib2lkYy1jbGllbnRpZCIsImF1ZCI6Imh0dHBzOi8vaWRlbnRpZnkwMS5pZGVudGlmeS5zYWZld2hlcmUuY29tL3J1bnRpbWUvb2F1dGgyL3Rva2VuLmlkcCIsImp0aSI6ImI3Y2Q3YzM3LWJlNmMtNDBmMy04MzhjLTNmYjMwYjg0OGFjMyIsImV4cCI6MjAzMjgyNTM5OCwibmJmIjoxNzE2MjkyNTk4LCJpYXQiOjE3MTYyOTI1OTh9.eEmv29qbwKZwNNsvlLEQjIiaBOtp7X2A9FCH7S6tCmahgcLk5uxWoipuZpF6xAa2dkQMH7xr6ZMviRl4H62iTkXjbzeoLexMCvUzIYHSnB_3NCp7MudmK7RszDGEv3ITR1YhXC-IIVAjQz7Ijmi3LCSqsFBshAJSUGH68c1b2lrq-KdFL-VbesMSvQ2eMBv5bt9t5KiC_pY5eqepcwRSbhXa41BqZ6_kvmuKoidFjkAArt18AAsWuibOxxf-nzm0IPl9aK0VH8ha84_S1EmvyzYpjq0BnNI8vU89c1-yhv7tHuOiCcl7e-Kc2Wg6Ow2uOQ6BUHMoHSxjhDmgf1cAbg
Token introspection response
The possible responses are:
HTTP Status | Description |
---|---|
200 | The server will always return a 200 status code, regardless of whether the submitted token is valid or not. The validity of the token is determined by the active parameter in the response body. Therefore, it is possible to receive a 200 status code even if the token is invalid or expired according to the specification. |
400 | Invalid or malformed request. |
401 | The request was denied due to invalid or missing client authentication. |
Successful response example
- Introspection response for a valid access token
{
"active": true,
"iss": "https://identify01.identify.safewhere.com/runtime/oauth2",
"sub": "demouser",
"jti": "4bcaca31-ff5d-4a71-9980-d7eff97f2750",
"token_type": "Bearer",
"token_usage": "access_token",
"client_id": "oauth2_codeflow_restapi_token_123456",
"iat": 1702280016,
"nbf": 1702280016,
"exp": 1702283616,
"aud": "https://identify01.identify.safewhere.com/runtime/"
}
For the access token containing the arc
and auth_time
claims, they should be included in the introspection response.
{
"active": true,
"iss": "https://identify01.identify.safewhere.com/runtime/oauth2",
"sub": "demouser",
"jti": "4bcaca31-ff5d-4a71-9980-d7eff97f2750",
"token_type": "Bearer",
"token_usage": "access_token",
"client_id": "oauth2_codeflow_restapi_token_123456",
"iat": 1702280016,
"nbf": 1702280016,
"exp": 1702283616,
"aud": "https://identify01.identify.safewhere.com/runtime/",
"arc": "urn:dk:gov:saml:attribute:AssuranceLevel:3",
"auth_time": 1702280033
}
- Introspection response for a valid refresh token
{
"active": true,
"iss": "https://identify01.identify.safewhere.com/runtime/oauth2",
"sub": "admin",
"scope": "identify*scim",
"token_usage": "refresh_token",
"client_id": "oauth2_codeflow_restapi_token_123456",
"iat": 1702270870,
"nbf": 1702270870,
"exp": 1765342870
}
- Introspection response for an invalid, expired or revoked token
{
"active": false
}
Error response example
- 400 Bad Request:
{
"error": "invalid_request",
"error_description": "Invalid client assertion type."
}
- 401 Unauthorized:
{
"error": "invalid_client",
"error_description": "Invalid client_id, client_secret or client_assertion: Please ensure that the connection setting was set up correctly."
}
Notes
Access tokens are not immediately invalidated when the corresponding refresh token is revoked. Users must manually invoke the revocation endpoint to revoke individual access tokens.
Security log event ids:
- Revocation request: 4940
- Revocation response: 4941
- Invalid revocation request: 4942
- Introspection request: 4950
- Introspection response: 4951
- Invalid introspection request: 4952
The event IDs for Revocation and Introspection requests (4940 and 4950) are only logged if the request meets the following criteria:
- Use the HTTP method
POST
. - Contain the Content-Type header
application/x-www-form-urlencoded
in its request header. - Include the required
token
parameter in its request body.
- Use the HTTP method
Both revocation endpoint and introspection endpoint only support the POST method. If a client uses an unsupported method, the Identify OAuth server will respond with a 405 error, like this:
{
"Message":"The requested resource does not support http method '[Invalid method name]'."
}
If the token_type_hint parameter is omitted, the revocation endpoint can revoke tokens of types supported by the current Identify server, such as access tokens, refresh tokens, authorization codes, etc.
Whenever a token is revoked, a RevokeOAuthAccessToken audit event type is recorded in the audit log system.