Skip to main content

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:

MechanismWho decidesWhenScope
Namespace options (allow_* flags, user-limited channels)You, in configOnce, at config timeEveryone in the namespace
Tokens (connection JWT, subscription JWT)Your backend, when it issues the tokenAt token-issue time, re-checked on token expiryPer user / per subscription
Proxies (connect, subscribe, publish proxy)Your backend, on every relevant eventAt the moment of the eventPer 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 clientsubscription token (recommended default)
To be notified on every subscribe / revoke access instantly / deliver initial datasubscribe proxy
One channel per user with almost no codeautomatic personal channel
Fine-grained, multi-channel grants without per-channel tokenscapabilities 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.

note

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:

  1. 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.
  2. 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.
  3. User-limited channel (#) โ€” if the namespace enables allow_user_limited_channels and the user ID matches, the subscription is accepted. For user-limited channels the proxy and allow_subscribe_for_client are not consulted.
  4. Subscribe proxy โ€” if enabled (and the channel is not user-limited), your backend decides.
  5. Connection capabilities PRO โ€” a sub capability from the connection token / connect proxy that matches the channel.
  6. allow_subscribe_for_client โ€” allows all authenticated (non-anonymous) connections; add allow_subscribe_for_anonymous to also allow anonymous ones. Not consulted for user-limited channels.

If none grant access, the subscription is denied.

Subscribe permission explorer

DENIED
Connection
User ID
Channel
# = user-limited ยท $ prefix = private channel
Namespace options
Tokens & capabilities
Subscription token
Connection capabilities PRO โ€” connection token caps / connect proxy
match: omit for exact, or wildcard / regex.
Grants permissions without a per-channel token. This operation needs the sub capability.
Decision order
  • ยท
    Subscription token
    No subscription token supplied.
  • ยท
    User-limited channel ("#")
    allow_user_limited_channels is not enabled.
  • ยท
    Subscribe proxy
    Subscribe proxy is not enabled for this namespace.
  • ยท
    Connection capabilities PRO
    No connection capabilities set (connection token / connect proxy).
  • ยท
    allow_subscribe_for_client
    allow_subscribe_for_client is not enabled.
  • โœ•
    Result
    No mechanism granted access โ€” 103: permission denied.
Implement thisThese settings currently produce DENIED. The snippets below reflect what you toggled โ€” adjust the options to grant access.
Centrifugo config
{
  "channel": {
    "namespaces": [
      {
        "name": "personal"
      }
    ]
  }
}
No namespace permission options are toggled on for this operation yet.
No token required for this configuration โ€” permission comes from namespace options/user-limited channel.
Mirrors Centrifugo's decision order for teaching purposes. Advanced knobs (CEL expressions, the bidirectional subscribe-stream proxy) are omitted for clarity. Server API calls from your backend always bypass these checks.

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.

caution

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.

caution

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.

caution

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โ€‹

tip

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:

  1. Publish proxy โ€” if publish_proxy_enabled, the proxy takes precedence over everything else. The built-in allow_publish_* flags and token capabilities are not consulted; the proxy response alone decides.
  2. allow_publish_for_client โ€” allows all authenticated connections (add allow_publish_for_anonymous for anonymous ones).
  3. allow_publish_for_subscriber โ€” allows connections currently subscribed to the channel they publish into.
  4. Connection capabilities PRO โ€” a pub capability from the connection token / connect proxy.
  5. Subscription capabilities PRO โ€” a pub capability from the subscription token allow / subscribe proxy for this channel.

If none grant access, the publication is denied.

Publish permission explorer

DENIED
Connection
User ID
Channel
# = user-limited ยท $ prefix = private channel
Namespace options
Tokens & capabilities
Connection capabilities PRO โ€” connection token caps / connect proxy
match: omit for exact, or wildcard / regex.
Grants permissions without a per-channel token. This operation needs the pub capability.
Subscription allow for this channel PRO โ€” subscription token allow / subscribe proxy. This operation needs pub.
Check pub to grant this operation for personal:17.
Decision order
  • ยท
    Publish proxy
    Publish proxy is not enabled. (When enabled it overrides all flags and capabilities below.)
  • ยท
    allow_publish_for_client
    allow_publish_for_client is not enabled.
  • ยท
    allow_publish_for_subscriber
    allow_publish_for_subscriber is not enabled.
  • ยท
    Connection capabilities PRO
    No connection capabilities set (connection token / connect proxy).
  • ยท
    Subscription capabilities PRO
    No per-channel capabilities from a subscription token / subscribe proxy.
  • โœ•
    Result
    No mechanism granted access โ€” 103: permission denied.
Implement thisThese settings currently produce DENIED. The snippets below reflect what you toggled โ€” adjust the options to grant access.
Centrifugo config
{
  "channel": {
    "namespaces": [
      {
        "name": "personal"
      }
    ]
  }
}
No namespace permission options are toggled on for this operation yet.
No token required for this configuration โ€” permission comes from namespace options.
Mirrors Centrifugo's decision order for teaching purposes. Advanced knobs (CEL expressions, the bidirectional subscribe-stream proxy) are omitted for clarity. Server API calls from your backend always bypass these checks.

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:

  1. allow_history_for_client โ€” allows all authenticated connections (add allow_history_for_anonymous for anonymous ones).
  2. allow_history_for_subscriber โ€” allows connections currently subscribed to the channel.
  3. Connection capabilities PRO โ€” an hst capability from the connection token / connect proxy.
  4. Subscription capabilities PRO โ€” an hst capability from the subscription token allow / subscribe proxy for this channel.

History permission explorer

DENIED
Connection
User ID
Channel
# = user-limited ยท $ prefix = private channel
Namespace options
Tokens & capabilities
Connection capabilities PRO โ€” connection token caps / connect proxy
match: omit for exact, or wildcard / regex.
Grants permissions without a per-channel token. This operation needs the hst capability.
Subscription allow for this channel PRO โ€” subscription token allow / subscribe proxy. This operation needs hst.
Check hst to grant this operation for personal:17.
Decision order
  • โ€“
    History configured
    History is configured (history_size and history_ttl > 0), so permission is evaluated.
  • ยท
    allow_history_for_client
    allow_history_for_client is not enabled.
  • ยท
    allow_history_for_subscriber
    allow_history_for_subscriber is not enabled.
  • ยท
    Connection capabilities PRO
    No connection capabilities set (connection token / connect proxy).
  • ยท
    Subscription capabilities PRO
    No per-channel capabilities from a subscription token / subscribe proxy.
  • โœ•
    Result
    No mechanism granted access โ€” 103: permission denied.
Implement thisThese settings currently produce DENIED. The snippets below reflect what you toggled โ€” adjust the options to grant access.
Centrifugo config
{
  "channel": {
    "namespaces": [
      {
        "name": "personal",
        "history_size": 100,
        "history_ttl": "300s"
      }
    ]
  }
}
`history_size` / `history_ttl` are example values โ€” tune them to your retention needs.
No token required for this configuration โ€” permission comes from namespace options.
Mirrors Centrifugo's decision order for teaching purposes. Advanced knobs (CEL expressions, the bidirectional subscribe-stream proxy) are omitted for clarity. Server API calls from your backend always bypass these checks.

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:

  1. allow_presence_for_client โ€” allows all authenticated connections (add allow_presence_for_anonymous for anonymous ones).
  2. allow_presence_for_subscriber โ€” allows connections currently subscribed to the channel.
  3. Connection capabilities PRO โ€” a prs capability from the connection token / connect proxy.
  4. Subscription capabilities PRO โ€” a prs capability from the subscription token allow / subscribe proxy for this channel.

Presence permission explorer

DENIED
Connection
User ID
Channel
# = user-limited ยท $ prefix = private channel
Namespace options
Tokens & capabilities
Connection capabilities PRO โ€” connection token caps / connect proxy
match: omit for exact, or wildcard / regex.
Grants permissions without a per-channel token. This operation needs the prs capability.
Subscription allow for this channel PRO โ€” subscription token allow / subscribe proxy. This operation needs prs.
Check prs to grant this operation for personal:17.
Decision order
  • โ€“
    Presence enabled
    Presence is enabled, so permission is evaluated.
  • ยท
    allow_presence_for_client
    allow_presence_for_client is not enabled.
  • ยท
    allow_presence_for_subscriber
    allow_presence_for_subscriber is not enabled.
  • ยท
    Connection capabilities PRO
    No connection capabilities set (connection token / connect proxy).
  • ยท
    Subscription capabilities PRO
    No per-channel capabilities from a subscription token / subscribe proxy.
  • โœ•
    Result
    No mechanism granted access โ€” 103: permission denied.
Implement thisThese settings currently produce DENIED. The snippets below reflect what you toggled โ€” adjust the options to grant access.
Centrifugo config
{
  "channel": {
    "namespaces": [
      {
        "name": "personal",
        "presence": true
      }
    ]
  }
}
No token required for this configuration โ€” permission comes from namespace options.
Mirrors Centrifugo's decision order for teaching purposes. Advanced knobs (CEL expressions, the bidirectional subscribe-stream proxy) are omitted for clarity. Server API calls from your backend always bypass these checks.

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 caps claim (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 match field selects how each channel string is compared to the requested channel: "" (default) exact match, wildcard, or regex.

  • Subscription capabilities live in the subscription JWT allow claim (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).