Channel permission model
When using the Centrifugo server API you don't need to think about channel permissions at all โ everything is allowed. In the server API case, the request to Centrifugo is issued by your application backend โ so you already have all the power to check any required permissions before issuing the API request.
The situation is different when we talk about the client real-time API โ subscribing to channels and calling publish, history and presence from a connection established over one of the bidirectional real-time transports. Centrifugo gives you several ways to control what a client may do, and this document is the single place that describes all of them.
There are many individual options, so before the reference sections below let's build a mental model that makes them fit together.
The mental modelโ
Every client permission decision comes down to two questions: who decides, and when. There are only three mechanisms, and everything else is a variation on them:
| Mechanism | Who decides | When | Scope |
|---|---|---|---|
Namespace options (allow_* flags, user-limited channels) | You, in config | Once, at config time | Everyone in the namespace |
| Tokens (connection JWT, subscription JWT) | Your backend, when it issues the token | At token-issue time, re-checked on token expiry | Per user / per subscription |
| Proxies (connect, subscribe, publish proxy) | Your backend, on every relevant event | At the moment of the event | Per event |
The same three mechanisms apply to all four operations โ subscribe, publish, history, presence. In Centrifugo PRO, tokens and proxies can additionally carry a capability object that grants fine-grained permissions for several channels at once (more on that in Capabilities below).
So instead of memorizing dozens of options, remember the grid: three mechanisms ร four operations, plus capabilities as the PRO way to batch permissions.
Choosing an approachโ
For the common case โ "let a specific user access a specific channel" โ this is the quick guide:
| If you wantโฆ | Use |
|---|---|
| A public channel (any authenticated connection may subscribe) | allow_subscribe_for_client |
| A per-user channel, checked at your backend, cached on the client | subscription token (recommended default) |
| To be notified on every subscribe / revoke access instantly / deliver initial data | subscribe proxy |
| One channel per user with almost no code | automatic personal channel |
| Fine-grained, multi-channel grants without per-channel tokens | capabilities in connection JWT / connect proxy PRO |
For a deeper tour of the options for a single personal channel, see the 101 ways to subscribe post.
Validate before you buildโ
Permissions are easiest to get wrong at the interaction level โ "this user, this channel, this config: allowed or not, and why?". Each section below embeds an interactive explorer that mirrors Centrifugo's real decision order. Toggle the options, pick a token/proxy outcome, and watch the exact order of checks that leads to ALLOWED or DENIED. Use it to confirm your permission model before writing a line of code.
The explorers run entirely in your browser and reproduce the server's decision order for teaching purposes. A few advanced knobs (CEL expressions, the bidirectional subscribe-stream proxy) are omitted for clarity. The authoritative behavior is always the server itself.
Subscribe permission modelโ
By default, a client's attempt to subscribe to a channel is rejected with a 103: permission denied error. Centrifugo evaluates the following mechanisms in order and the first one that grants access wins:
- Private-prefix gate โ if the channel name starts with
channel.private_prefix($by default), a subscription without a token is rejected immediately, regardless of any option below. This helps avoid accidentally exposing channels. - Subscription token โ if a token is supplied, it alone decides the subscription (all mechanisms below are skipped). A valid token accepts; an invalid one rejects.
- User-limited channel (
#) โ if the namespace enablesallow_user_limited_channelsand the user ID matches, the subscription is accepted. For user-limited channels the proxy andallow_subscribe_for_clientare not consulted. - Subscribe proxy โ if enabled (and the channel is not user-limited), your backend decides.
- Connection capabilities PRO โ a
subcapability from the connection token / connect proxy that matches the channel. allow_subscribe_for_clientโ allows all authenticated (non-anonymous) connections; addallow_subscribe_for_anonymousto also allow anonymous ones. Not consulted for user-limited channels.
If none grant access, the subscription is denied.
Subscribe permission explorer
DENIED# = user-limited ยท $ prefix = private channelcaps / connect proxymatch: omit for exact, or wildcard / regex.sub capability.- ยทSubscription tokenNo subscription token supplied.
- ยทUser-limited channel ("#")allow_user_limited_channels is not enabled.
- ยทSubscribe proxySubscribe proxy is not enabled for this namespace.
- ยทConnection capabilities PRONo connection capabilities set (connection token / connect proxy).
- ยทallow_subscribe_for_clientallow_subscribe_for_client is not enabled.
- โResultNo mechanism granted access โ 103: permission denied.
{
"channel": {
"namespaces": [
{
"name": "personal"
}
]
}
}Below are the details of each mechanism.
Provide subscription tokenโ
A client can provide a subscription token in the subscribe request. See the format of the token. If a client provides a valid token then the subscription is accepted. In Centrifugo PRO, a subscription token can additionally grant publish, history and presence permissions to a client via the allow claim.
For namespaces with allow_subscribe_for_client ON, Centrifugo does not allow subscribing to channels starting with channel.private_prefix ($ by default) without a token. This limitation exists to help users migrate to Centrifugo v4 without security risks.
Configure subscribe proxyโ
If a client subscribes to a namespace with a configured subscribe proxy (subscribe_proxy_enabled), then depending on the proxy response the subscription is accepted or not.
If a namespace has a configured subscribe proxy, but the client came with a token โ then the subscribe proxy is not used; the token decides. If a client subscribes to a user-limited channel โ the subscribe proxy is not used either.
Use user-limited channelsโ
If a client subscribes to a user-limited channel and there is a user ID match, then the subscription is accepted. A user-limited channel contains a # followed by a comma-separated list of allowed user IDs, e.g. personal:#17 or chat:#17,42.
User-limited channels must be enabled in a namespace using the allow_user_limited_channels channel option.
Use allow_subscribe_for_client namespace optionโ
allow_subscribe_for_client allows all authenticated non-anonymous connections to subscribe to all channels in a namespace.
Turning this option on effectively makes the namespace public โ no per-user subscribe permissions are checked (only that the connection is authenticated, i.e. has a non-empty user ID). Make sure this is really what you want in terms of channel security.
To additionally allow subscribing for anonymous connections take a look at the allow_subscribe_for_anonymous option.
Subscribe capabilities in connection tokenโ
Centrifugo PRO only
A connection token can contain a capability object to allow the user to subscribe to channels. See Capabilities.
Subscribe capabilities in connect proxyโ
Centrifugo PRO only
A connect proxy can return a capability object to allow the user to subscribe to channels.
Publish permission modelโ
In the idiomatic Centrifugo use case, data is published to channels from the application backend (over the server API). The backend can validate data and save it to persistent storage before publishing in real-time. When publishing from the client-side the backend does not receive the publication data at all โ it just goes through Centrifugo (except when using a publish proxy). Direct publications from the client-side are still useful in some cases (like typing indicators in chat).
By default, a client's attempt to publish to a channel is rejected with a 103: permission denied error. Centrifugo evaluates the following in order, first match wins:
- Publish proxy โ if
publish_proxy_enabled, the proxy takes precedence over everything else. The built-inallow_publish_*flags and token capabilities are not consulted; the proxy response alone decides. allow_publish_for_clientโ allows all authenticated connections (addallow_publish_for_anonymousfor anonymous ones).allow_publish_for_subscriberโ allows connections currently subscribed to the channel they publish into.- Connection capabilities PRO โ a
pubcapability from the connection token / connect proxy. - Subscription capabilities PRO โ a
pubcapability from the subscription tokenallow/ subscribe proxy for this channel.
If none grant access, the publication is denied.
Publish permission explorer
DENIED# = user-limited ยท $ prefix = private channelcaps / connect proxymatch: omit for exact, or wildcard / regex.pub capability.allow for this channel PRO โ subscription token allow / subscribe proxy. This operation needs pub.pub to grant this operation for personal:17.- ยทPublish proxyPublish proxy is not enabled. (When enabled it overrides all flags and capabilities below.)
- ยทallow_publish_for_clientallow_publish_for_client is not enabled.
- ยทallow_publish_for_subscriberallow_publish_for_subscriber is not enabled.
- ยทConnection capabilities PRONo connection capabilities set (connection token / connect proxy).
- ยทSubscription capabilities PRONo per-channel capabilities from a subscription token / subscribe proxy.
- โResultNo mechanism granted access โ 103: permission denied.
{
"channel": {
"namespaces": [
{
"name": "personal"
}
]
}
}Use allow_publish_for_client namespace optionโ
allow_publish_for_client allows publications to channels of a namespace for all authenticated client connections. Add allow_publish_for_anonymous to also allow anonymous connections.
Use allow_publish_for_subscriber namespace optionโ
allow_publish_for_subscriber allows publications to channels of a namespace for all connections currently subscribed to the channel they want to publish into.
Configure publish proxyโ
If a client publishes to a namespace with a configured publish proxy, then depending on the proxy response the publication is accepted or not.
When a publish proxy is enabled for a namespace it takes precedence: all client publishes to channels in that namespace are routed to the proxy, and the proxy response alone decides whether the publication is accepted. The built-in allow_publish_for_client / allow_publish_for_subscriber flags and token publish capabilities are not consulted in this case.
Publish capabilities in connection tokenโ
Centrifugo PRO only
A connection token can contain a capability object to allow the client to publish to channels.
Publish capability in subscription tokenโ
Centrifugo PRO only
A subscription token can contain a pub capability in its allow claim to allow the client to publish to that channel.
Publish capabilities in connect proxyโ
Centrifugo PRO only
A connect proxy can return a capability object to allow the client to publish to certain channels.
Publish capability in subscribe proxyโ
Centrifugo PRO only
A subscribe proxy can return an allow list containing pub to allow the subscriber to publish to the channel.
History permission modelโ
By default, a client's attempt to call history for a channel is rejected with a 103: permission denied error. History must first be configured for the namespace (history_size and history_ttl greater than zero) โ otherwise the call returns 108: not available before any permission check. When history is configured, Centrifugo evaluates the following in order, first match wins:
allow_history_for_clientโ allows all authenticated connections (addallow_history_for_anonymousfor anonymous ones).allow_history_for_subscriberโ allows connections currently subscribed to the channel.- Connection capabilities PRO โ an
hstcapability from the connection token / connect proxy. - Subscription capabilities PRO โ an
hstcapability from the subscription tokenallow/ subscribe proxy for this channel.
History permission explorer
DENIED# = user-limited ยท $ prefix = private channelcaps / connect proxymatch: omit for exact, or wildcard / regex.hst capability.allow for this channel PRO โ subscription token allow / subscribe proxy. This operation needs hst.hst to grant this operation for personal:17.- โHistory configuredHistory is configured (history_size and history_ttl > 0), so permission is evaluated.
- ยทallow_history_for_clientallow_history_for_client is not enabled.
- ยทallow_history_for_subscriberallow_history_for_subscriber is not enabled.
- ยทConnection capabilities PRONo connection capabilities set (connection token / connect proxy).
- ยทSubscription capabilities PRONo per-channel capabilities from a subscription token / subscribe proxy.
- โResultNo mechanism granted access โ 103: permission denied.
{
"channel": {
"namespaces": [
{
"name": "personal",
"history_size": 100,
"history_ttl": "300s"
}
]
}
}Use allow_history_for_client namespace optionโ
allow_history_for_client allows history requests to all channels in a namespace for all authenticated client connections. Add allow_history_for_anonymous to also allow anonymous connections.
Use allow_history_for_subscriber namespace optionโ
allow_history_for_subscriber allows history requests for all connections currently subscribed to the channel they want to call history for.
History capabilities in connection tokenโ
Centrifugo PRO only
A connection token can contain a capability object to allow the user to call history for channels.
History capability in subscription tokenโ
Centrifugo PRO only
A subscription token can contain an hst capability in its allow claim to allow the user to call history for that channel.
History capabilities in connect proxyโ
Centrifugo PRO only
A connect proxy can return a capability object to allow the client to call history for certain channels.
History capability in subscribe proxyโ
Centrifugo PRO only
A subscribe proxy can return an allow list containing hst to allow the subscriber to call history for the channel.
Presence permission modelโ
By default, a client's attempt to call presence for a channel is rejected with a 103: permission denied error. Presence must first be enabled for the namespace โ otherwise the call returns 108: not available before any permission check. When presence is enabled, Centrifugo evaluates the following in order, first match wins:
allow_presence_for_clientโ allows all authenticated connections (addallow_presence_for_anonymousfor anonymous ones).allow_presence_for_subscriberโ allows connections currently subscribed to the channel.- Connection capabilities PRO โ a
prscapability from the connection token / connect proxy. - Subscription capabilities PRO โ a
prscapability from the subscription tokenallow/ subscribe proxy for this channel.
Presence permission explorer
DENIED# = user-limited ยท $ prefix = private channelcaps / connect proxymatch: omit for exact, or wildcard / regex.prs capability.allow for this channel PRO โ subscription token allow / subscribe proxy. This operation needs prs.prs to grant this operation for personal:17.- โPresence enabledPresence is enabled, so permission is evaluated.
- ยทallow_presence_for_clientallow_presence_for_client is not enabled.
- ยทallow_presence_for_subscriberallow_presence_for_subscriber is not enabled.
- ยทConnection capabilities PRONo connection capabilities set (connection token / connect proxy).
- ยทSubscription capabilities PRONo per-channel capabilities from a subscription token / subscribe proxy.
- โResultNo mechanism granted access โ 103: permission denied.
{
"channel": {
"namespaces": [
{
"name": "personal",
"presence": true
}
]
}
}Use allow_presence_for_client namespace optionโ
allow_presence_for_client allows presence requests to all channels in a namespace for all authenticated client connections. Add allow_presence_for_anonymous to also allow anonymous connections.
Use allow_presence_for_subscriber namespace optionโ
allow_presence_for_subscriber allows presence requests for all connections currently subscribed to the channel they want to call presence for.
Presence capabilities in connection tokenโ
Centrifugo PRO only
A connection token can contain a capability object to allow the user to call presence for channels.
Presence capability in subscription tokenโ
Centrifugo PRO only
A subscription token can contain a prs capability in its allow claim to allow the user to call presence for that channel.
Presence capabilities in connect proxyโ
Centrifugo PRO only
A connect proxy can return a capability object to allow the client to call presence for certain channels.
Presence capability in subscribe proxyโ
Centrifugo PRO only
A subscribe proxy can return an allow list containing prs to allow the subscriber to call presence for the channel.
Capabilities PROโ
Capabilities are the Centrifugo PRO way to grant several permissions at once, instead of using a per-channel flag or token. They come in two shapes:
-
Connection capabilities live in the connection JWT
capsclaim (or the connect proxy result). Each entry grants a set of operations for a set of channels, with an optional matching mode:"caps": [
{"channels": ["personal:17"], "allow": ["sub"]},
{"channels": ["news:*"], "match": "wildcard", "allow": ["sub", "hst"]}
]The
matchfield selects how each channel string is compared to the requested channel:""(default) exact match,wildcard, orregex. -
Subscription capabilities live in the subscription JWT
allowclaim (or the subscribe proxy result). This is a flat list of operations for the single channel of that subscription:{"channel": "personal:17", "allow": ["pub", "hst", "prs"]}
The valid operation strings are sub (subscribe), pub (publish), hst (history) and prs (presence). Connection capabilities are checked before subscription capabilities in every operation's decision order.
Positioning permission modelโ
The server can turn on positioning for all channels in a namespace using the force_positioning option, or a client can create positioned subscriptions (in which case the client must have access to the history capability).
Recovery permission modelโ
The server can turn on automatic recovery for all channels in a namespace using the force_recovery option, or a client can create recoverable subscriptions (in which case the client must have access to the history capability).
Join/Leave permission modelโ
The server can force sending join/leave messages to all subscribers for all channels in a namespace using the force_push_join_leave option, or a client can ask the server to include join/leave messages upon subscribing (in which case the client must have access to the presence capability).