Skip to main content

User blocking and token revocation

Centrifugo PRO provides protective APIs for blocking users and revoking tokens. Both features share a similar design: information is distributed across the cluster and kept in memory by default, with optional persistent storage via Redis or PostgreSQL. Entries expire automatically to keep the working set small – all checks are performed over in-memory data structures, so they are cheap and have minimal performance impact.

User blocking

When a user is blocked they will be disconnected from Centrifugo immediately and also on the next connect attempt right after the JWT is decoded (so that Centrifugo has a user ID) or after the result from the connect proxy is received. In case of using a connect proxy you can actually disconnect the user yourself by implementing a blocking check on the application backend side – but the possibility to block a user in Centrifugo can still be helpful.

User block feature is enabled by default in Centrifugo PRO (blocking information will be stored in process memory). To keep blocking information persistently you need to configure a persistence engine – see persistence configuration below.

block_user

Example:

curl --header "Content-Type: application/json" \
--header "X-API-Key: <API_KEY>" \
--request POST \
--data '{"user": "2695", "expire_at": 1635845122}' \
http://localhost:8000/api/block_user

BlockUserRequest

Parameter nameParameter typeRequiredDescription
userstringyesUser ID to block
expire_atintnoUnix time in the future when user blocking information should expire (Unix seconds). While optional we recommend to use a reasonably small expiration time to keep working set of blocked users small (since Centrifugo nodes periodically load all entries from the storage to construct in-memory cache).

BlockUserResult

Empty object at the moment.

unblock_user

Example:

curl --header "Content-Type: application/json" \
--header "X-API-Key: <API_KEY>" \
--request POST \
--data '{"user": "2695"}' \
http://localhost:8000/api/unblock_user

UnblockUserRequest

Parameter nameParameter typeRequiredDescription
userstringyesUser ID to unblock

UnblockUserResult

Empty object at the moment.

Token revocation

Centrifugo PRO provides two ways to revoke tokens:

  1. Revoke token by ID: based on jti claim in the case of JWT.
  2. Revoke all user's tokens issued before certain time: based on iat in the case of JWT.

When a token is revoked, the client with such a token will be disconnected from Centrifugo shortly. An attempt to connect with a revoked token won't succeed.

Token revocation features (both revocation by token ID and user token invalidation by issue time) are enabled by default in Centrifugo PRO (as soon as your JWTs have jti and iat claims you will be able to use revocation APIs). By default revocation information is kept in process memory. To persist it, configure a storage engine – see persistence configuration below.

revoke_token

Allows revoking individual tokens. For example, this may be useful when token leakage has been detected and you want to revoke access for a particular token. BTW, Centrifugo PRO provides a user_connections API which has information about tokens for active user connections (if set in JWT).

caution

This API assumes that JWTs you are using contain "jti" claim which is a unique token ID (according to RFC).

Example:

curl --header "Content-Type: application/json" \
--header "X-API-Key: <API_KEY>" \
--request POST \
--data '{"uid": "xxx-xxx-xxx", "expire_at": 1635845122}' \
http://localhost:8000/api/revoke_token

revoke_token params

Parameter nameParameter typeRequiredDescription
uidstringyesToken unique ID (JTI claim in case of JWT)
expire_atintnoUnix time in the future when revocation information should expire (Unix seconds). While optional we recommend to use a reasonably small expiration time (matching the expiration time of your JWTs) to keep working set of revocations small (since Centrifugo nodes periodically load all entries from the database table to construct in-memory cache).

revoke_token result

Empty object at the moment.

invalidate_user_tokens

Allows revoking all tokens for a user which were issued before a certain time. For example, this may be useful after user changed a password in an application.

caution

This API assumes that JWTs you are using contain "iat" claim which is a time token was issued at (according to RFC).

Example:

curl --header "Content-Type: application/json" \
--header "X-API-Key: <API_KEY>" \
--request POST \
--data '{"user": "test", "issued_before": 1635845022, "expire_at": 1635845122}' \
http://localhost:8000/api/invalidate_user_tokens

InvalidateUserTokensRequest

Parameter nameParameter typeRequiredDescription
userstringyesUser ID to invalidate tokens for
issued_beforeintnoAll tokens issued before this Unix time will be considered revoked (in case of JWT this requires iat to be properly set in the JWT); if not provided the server uses current time
expire_atintnoUnix time in the future when revocation information should expire (Unix seconds). While optional we recommend to use a reasonably small expiration time (matching the expiration time of your JWTs) to keep working set of revocations small (since Centrifugo nodes periodically load all entries from the database table to construct in-memory cache).

InvalidateUserTokensResult

Empty object.

Persistence configuration

By default both user blocking and token revocation data is kept in process memory and will be lost on restart. To persist this data, configure a storage engine.

Two persistent engines are supported:

  1. redis
  2. database

Redis persistence engine

config.json
{
"user_block": {
"storage_type": "redis",
"redis": {
"address": "localhost:6379"
}
},
"token_revoke": {
"storage_type": "redis",
"redis": {
"address": "localhost:6379"
}
},
"user_tokens_invalidate": {
"storage_type": "redis",
"redis": {
"address": "localhost:6379"
}
}
}
danger

Unlike many other Redis features in Centrifugo, consistent sharding is not supported for blocking and revocation data. The reason is that we don't want to lose this information when an additional Redis node is added. So only one Redis shard can be provided for user_block, token_revoke and user_tokens_invalidate features. This should be fine given that the working set should be reasonably small and old entries expire. If you try to set several Redis shards here, Centrifugo will exit with an error on start.

caution

One more thing you may notice is that Redis configuration here does not have the use_redis_from_engine option. The reason is that since Redis is not shardable here, reusing Redis configuration could cause problems at the moment of Redis scaling – which we want to avoid, thus requiring explicit configuration here.

Database persistence engine

Only PostgreSQL is supported.

config.json
{
"database": {
"enabled": true,
"postgresql": {
"dsn": "postgresql://postgres:pass@127.0.0.1:5432/postgres"
}
},
"user_block": {
"storage_type": "database"
},
"token_revoke": {
"storage_type": "database"
},
"user_tokens_invalidate": {
"storage_type": "database"
}
}
tip

To quickly start local PostgreSQL database:

docker run -it --rm -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=pass -p 5432:5432 postgres:15