Tokens
Clients authenticate with access tokens.
Token format
Access tokens are strings like:
AT_<token_id>_<secret>
token_id: 16 bytes encoded in hex (32 hex characters)secret: 16 bytes encoded in hex (32 hex characters)
Tokens are created by an admin via the REST API and given to clients.
Token lifetime (expires_at)
Each token has an expiry time:
- expires_at: ISO 8601 (example:
2026-02-10T12:00:00Z) - Maximum TTL: 24 hours. The
expires_atfield must not exceed 24 hours from the current server time. Requests with a longer TTL are rejected (HTTP 400 / gRPCINVALID_ARGUMENT). - After expiry, authentication fails for new connections.
- To keep a token alive longer than 24 hours, use
PUT /v1/refresh-token(or gRPCRefreshToken) to extend it periodically (up to 24 hours each time).
Some deployments support graceful deactivation without forcing disconnects: set expires_at to a past time via refresh. New authentications fail, and the token is removed shortly after. Details depend on deployment and are described in Client configuration.
Permissions
Each token carries a list of tenant_grants that define:
- allow_channels_pub: which channels the client can publish to (pub-token rules – literals, alternatives,
#,>, but no?or*). - allow_channels_sub: which subscription patterns the client is allowed to send (sub-token rules – full syntax with
?,*, alternatives,#,>).
Both use similar dot-separated segment syntax with alternatives and tail wildcards. The key difference: publish rules do not allow ? and *, because publish targets are always concrete channel names. Subscribe rules allow ? and * because subscription patterns can contain wildcards.
Full details, syntax, and examples: Permissions model.
Network restrictions (optional)
Tokens may restrict where they can be used:
- allow_ip_masks: list of exact IPs or CIDR ranges. If non-empty, only clients with matching IPs can authenticate.
- allow_regions: list of regions where authentication may be performed (example:
["EU"]). - allowed_ws_origin: WebSocket-only. If non-empty, the browser
Originheader must match one of the listed values.
These fields are described in detail in Client configuration.
How tokens are passed to the server
The mechanism depends on the protocol:
-
WebSocket (two methods, checked in priority order):
Authorization: Bearer AT_...header – recommended for server-side clients.Sec-WebSocket-Protocolsubprotocol – for browser clients that cannot set custom headers. The token is sent with anat.prefix alongside the real protocol name:
The server echoes back only the real protocol (new WebSocket(url, ["llps.v1", "at.AT_<id>_<secret>"])llps.v1), never the token.
-
gRPC: via metadata (for example an
authorizationmetadata entry with valueBearer AT_...).
See:
What not to do
- Do not put tokens into logs.
- Do not embed long-lived tokens into client-side code that ships to users (use short-lived tokens, or a backend exchange flow).