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 discovery endpoint of your Identify instance to see if the revocation_endpoint
and the introspection_endpoint
have been supported:
"introspection_endpoint": "https://dev.safewhere.local/runtime/oauth2/introspect.idp",
"revocation_endpoint": "https://dev.safewhere.local/runtime/oauth2/revoke.idp",
"introspection_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"],
"revocation_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"]
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 https://#yourdomain/runtime/oauth2/revoke.idp
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 https://#yourdomain/runtime/oauth2/revoke.idp
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
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
HTTP/1.1 200
Content-Type: application/json; charset=utf-8
{}
Error response example
- 400 Bad Request:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{"error":"invalid_request","error_description":"The mandatory 'Content-Type' header must be specified."}
- 401 Unauthorized:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
{"error":"invalid_client","error_description":"Invalid client_id or client_secret: Please ensure that the connection setting was set up correctly."}
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 https://#yourdomain/runtime/oauth2/introspect.idp
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 https://#yourdomain/runtime/oauth2/introspect.idp
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
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
HTTP/1.1 200
Content-Type: application/json; charset=utf-8
{
"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/"
}
- Introspection response for a valid refresh token
HTTP/1.1 200
Content-Type: application/json; charset=utf-8
{
"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
HTTP/1.1 200
Content-Type: application/json; charset=utf-8
{
"active": false
}
Error response example
- 400 Bad Request:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{"error":"invalid_request","error_description":"The mandatory 'Content-Type' header must be specified."}
- 401 Unauthorized:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
{"error":"invalid_client","error_description":"Invalid client_id or client_secret: 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.