Revocation
Revoke a refresh token or an access token your client holds, and what the endpoint does and does not tell you.
On this page
Revocation (RFC 7009) lets your client tell identity that a token is no longer wanted: when a person signs out of your application, when you discover a token leaked, or when you drop a failed login.
Request#
POST to the revocation_endpoint from discovery, which is /revoke, as application/x-www-form-urlencoded.
| Parameter | Rule |
|---|---|
client_id | Required exactly once. |
token | Required exactly once. A refresh token or an access token. |
| Client authentication | As for the token endpoint: a client assertion, and a DPoP proof if your client requires one. |
token_type_hint is ignored. Identity recognises a refresh token by its form and treats anything else as an access token.
What happens#
| Token | Effect |
|---|---|
| A refresh token issued to your client | The refresh token and the rest of its family are revoked. Every refresh token that came from the same sign-in stops working, and no access token can be obtained with them. |
| An access token your client may see | That is a token whose audience is your client, that was issued to your client, or whose audience is a resource your own application owns (the same rule as introspection). If it is currently active, it is refused from now on, until its natural expiry. |
| Anything else | Nothing. |
A revoked access token is refused by introspection and by userinfo. An API that verifies the JWT locally cannot see the revocation until it expires, which is at most 15 minutes. That is the cost of local verification; see Access token.
Revoking a token does not end the person's identity session and does not sign them out elsewhere. For that, use end session.
Response#
200 with an empty body and Cache-Control: no-store, and a DPoP-Nonce header.
The same 200 comes back for a token that was revoked, unknown, expired, malformed, or belongs to another client. This is required by RFC 7009: the endpoint is never a way to find out whether a token exists or who holds it. Do not read 200 as proof that a token was live.
Errors#
Only your client can fail, not the token.
| Status | error | When |
|---|---|---|
400 | invalid_request | A wrong content type, an oversized body, or token missing or repeated. |
401 | invalid_client | client_id missing, unknown or malformed, or authentication failed. |
400 | use_dpop_nonce, invalid_dpop_proof | Your client requires DPoP and the proof lacks a current nonce or is invalid. Retry once with the DPoP-Nonce value. |
429 | Refused for too many requests. Honour Retry-After. |
Worked example#
curl -s -o /dev/null -w '%{http_code}\n' https://identity.tdacorp.in/revoke \ -H "DPoP: $DPOP_PROOF" \ --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=$REFRESH_TOKEN"200With the SDK this is rp.revoke(token). It throws if the issuer publishes no revocation endpoint.
Security notes#
- Revoke the refresh token when a person signs out of your app, not only your own cookie. Otherwise a stolen refresh token keeps working until it expires.
- Revoke a token you obtained but cannot use. The SDK does this for you when the ID token fails verification.
- Do not retry blindly. A
200is final. A failure to reach the endpoint is a reason to try again, with a new client assertion each time. - Revocation is per client. You can revoke refresh tokens issued to your client, and access tokens your client may introspect. A person revokes a whole application from their account, and ending the sign-in session revokes everything it produced; see Connected applications.