Revocation
Revocation permanently invalidates an API token by setting its valid field to
0 in the database. After that happens, the
verification process rejects the key,
and the token can no longer be used for machine-to-machine access.
The IAM service keeps revoked token rows instead of deleting them during the standard revoke flow. This gives you a stable way to disable leaked, rotated, or no longer needed tokens while preserving their metadata for later auditing.
The direct library function revokeApiKey is idempotent. If the
provided token is already invalid, missing, or does not pass verification, it
still returns a success payload. The route behaves differently,
because it only looks up currently valid tokens before dispatching the
revocation.
You can revoke a token in 3 ways:
- Directly calling
revokeApiKey. - Using the
privateActionManagerto validate ownership before revoking. - Calling the
POST /api/manage/revokeendpoint from an authenticated client.
Revoking Tokens
You can revoke tokens either directly in the library or through the route. The direct helper focuses on the token itself, while the route adds ownership validation and authenticated client protections.
Using the library
To revoke a token directly, you call revokeApiKey. This function hashes the
provided token when needed, verifies it against the stored privilege, and then
marks the token as invalid.
import { revokeApiKey } from '@riavzon/auth'
const token = 'api_1234'
const privilege = 'restricted'
const results = await revokeApiKey(token, privilege)
if (!results.ok) {
console.error(results.reason)
}
On success you can get back one of two payloads. When the token is valid and the privilege matches, the response contains the revoked token id and user id:
{
ok: true,
date: new Date().toISOString(),
data: {
msg: 'Token invalided successfully',
invalidedTokenId: 12,
userId: 42
}
}
If the token is already invalid, missing, or does not pass verification, the
function still returns ok: true with a string payload:
{
ok: true,
date: new Date().toISOString(),
data: 'Token invalided successfully'
}
On error, such as a database failure, you get:
{
ok: false,
date: new Date().toISOString(),
reason: 'Error invalidating token'
}
Signature
The direct helper exposes the following signature:
export async function revokeApiKey(
rawKey: string,
providedPrivilege: 'demo' | 'restricted' | 'protected' | 'full' | 'custom',
): Promise<Results<{msg: string, invalidedTokenId: number, userId: number} | string>>
Parameters
| Field | Type | Description |
|---|---|---|
rawKey | string | The token to be revoked. It can be hashed or Raw. |
providedPrivilege | 'demo' | 'restricted' | 'protected' | 'full' | 'custom' | The privilege assigned to the token you want to revoke. |
publicIdentifier, and it bypasses IP
restriction checks and usage counter updates during its internal verification
step. Only call it directly in trusted server-side code.With the privateActionManager
The safest internal method is using the privateActionManager. This function
checks the publicIdentifier, token id, token name, user id, and current valid
status before dispatching the revocation.
const revokeRes = await privateActionManager(userId, tokenId, publicIdentifier, tokenName, {
action: 'revoke'
})
The privateActionManager returns the response of revokeApiKey directly.
Learn more at the
introduction page.
valid = 1. Because of that, manager-based
revocation does not behave like the direct revokeApiKey call when the token
is already revoked.Using the route
Let's say you want to revoke a token from your authenticated client or BFF.
POST /api/manage/revoke body:
{
"tokenId": 12,
"publicIdentifier": "public_identifier",
"name": "the token name"
}
On success you will get the following response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"ok": true,
"date": "current date",
"data": {
"msg": "Token invalided successfully",
"invalidedTokenId": 12,
"userId": 42
}
}
Aside from the standard errors related to authentication, rate limits, and provided bad data, the route returns the same success object the library users get when it revokes an active token.
If the body does not match the schema, the route returns:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"ok": false,
"date": "current date",
"reason": "Bad Request"
}
If the publicIdentifier checksum is invalid, the token does not belong to the
current user, the token is already revoked, or the underlying revoke action
fails, the route returns a 401 response with the reason provided by
privateActionManager, such as Invalid identity, Bad Request, or
Error invalidating token:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
{
"ok": false,
"date": "current date",
"reason": "reason from privateActionManager"
}
Rate Limits
The endpoint also enforces rate limits controlled under the following configuration options:
rate_limiters.apiTokensLimiters.operationRateLimits.revokeTokensLimiter- The main limiter for the revoke endpoint. The default allows 5 revocations in a window of 10 minutes and will trigger a block for 2 hours if this limit is met. Consecutive triggers in this period will block the client permanently.rate_limiters.apiTokensLimiters.generalUnionLimiter- AburstLimiterand aslowLimiterunion limiter. It enforces no more than one request per second, and only 50 per minute. No consecutive triggers in this limiter are provided, and triggering it again will result in a permanent ban. The limiter is restarted on successful revocations.burstLimiter- Will block the client for 15 minutes.slowLimiter- Will block for 1 hour.
Configuration Reference
These configuration keys control revoke-specific throttling in the service.
Rate limiters
The revocation flow relies on the following limiter configuration:
| Limiter | Description |
|---|---|
rate_limiters.apiTokensLimiters.operationRateLimits.revokeTokensLimiter | The main rate limiter for the revoke endpoint |
rate_limiters.apiTokensLimiters.generalUnionLimiter | General burst limiter |