Security best practices

PubNub security rests on two independent controls. Access Manager decides who can act on a channel, channel group, or user record. Encryption decides who can read the content that travels over it. A third control, the audit log, records who changed either one.

Architectural choices covers why access control belongs in your design from the start. This page works through the reasoning behind that design. It covers how to structure the token-issuing flow access control depends on, and why the secret key that issues tokens needs its own handling. It also covers when encryption needs to go beyond the TLS that's already on by default.

Design a token-issuing flow, not a key hand-off​

Without Access Manager, any client holding your publish and subscribe keys can read and write every channel on that keyset. Access Manager doesn't remove that risk by hiding the keys better. It adds a token: a signed, time-limited grant that names exactly what the holder can do. PubNub checks that token alongside the publish and subscribe keys the client already uses to reach the keyset, not instead of them.

The secret key grants privileged access to your PubNub application. It must remain on a trusted server and must never be included in client applications. Your server authenticates the user by whatever method your application already uses, then calls PubNub's grant API with the secret key to produce a token. The client never sees the secret key, only the token that call returns. The flow runs in five steps:

  1. The client app sends a login request to your server.
  2. Your server calls the PubNub grant API with the secret key.
  3. PubNub returns a signed, time-limited token to your server.
  4. Your server hands the token to the client.
  5. The client presents the token on every request to PubNub.

Shipping the secret key inside the client skips this flow. A leaked secret key lets an attacker issue tokens with any permission on the keyset. You also can't rotate a key embedded in a shipped app without a new release.


A token adds three things that publish and subscribe keys alone don't give you. It expires on its own, since every grant requires a TTL (Time To Live). It can bind to a single authorized User ID, so PubNub rejects it if it's presented with a different User ID. That binding doesn't make a stolen token safe to lose: the User ID a token is bound to travels with the token and with every request the client sends, so whoever holds the token can read that User ID and use it to send requests as that user. Handle a token like any other bearer secret, not like a public identifier. And a token names permissions per resource rather than per keyset, down to read on one channel and read, write on another.

A RE2 (Regular Expression 2) pattern covers many channels by name in a single token, instead of listing each one. Refer to Access Manager for the full permission and TTL model, and to Grant, change, and revoke permissions for the call that issues a token.

The client keeps its publish and subscribe keys through this whole flow. It initializes the SDK with them as always, then separately sets the token your server issued:

1import PubNub from 'pubnub';
2
3// The publish and subscribe keys identify your keyset. They stay in the client configuration.
4const pubnub = new PubNub({
5 publishKey: 'YOUR_PUBLISH_KEY',
6 subscribeKey: 'YOUR_SUBSCRIBE_KEY',
7 userId: 'YOUR_USER_ID',
8});
9
10// Your server holds the secret key, authenticates the user, and returns a token
11// granted for this User ID. Replace the URL with your own token endpoint.
12const response = await fetch('https://your-server.example.com/pubnub-token', {
13 credentials: 'include',
14});
15if (!response.ok) {
show all 21 lines

Deliver that token to the client only over TLS, from an authenticated call to your own server, the same way you'd deliver a password or a session cookie. Store it where other code on the device can't read it, keep its TTL short, and revoke it when a session ends or a user is removed. Refer to Grant, change, and revoke permissions for the revoke call.

Building this flow after you've already shipped a client with static keys costs more than building it first. Every install of that client keeps working exactly as before, unrestricted, until it's updated. You can't force that update. Design the token-issuing endpoint alongside your login flow, before the first client build goes out.

Treat the secret key as a root credential​

A leaked publish or subscribe key exposes whatever access that key already carries. A leaked secret key exposes everything the keyset could ever grant, because the secret key is what issues tokens in the first place. Whoever holds it can call the grant API themselves and mint a token with any permission on any resource, whether or not your application ever intended to grant it.

That difference is why the secret key needs handling a publish key doesn't. It never belongs in a client build, a mobile app bundle, or a public repository. It belongs only in the server-side SDK instance that calls the grant API. Refer to Initialize a server SDK with a secret key for that setup.

Because the blast radius of a leaked secret key is unbounded, plan to rotate it before you need to. Paid plans support secret key rotation from the Admin Portal, where you can stage up to five secret keys per keyset with future expiry dates. Staging a replacement key ahead of time gives a compromised key an expiry date without a service interruption.

Your server switches to the new key. The old one stops working when its staged expiry arrives, instead of the moment you notice the leak. Every rotation is written to the audit log automatically, so a rotation is traceable after the fact. Refer to Make every administrative change traceable for the rest of what that log covers.

Decide whether PubNub itself should be able to read your data​

All connections to PubNub use TLS 1.2 by default, so data in transit is already encrypted regardless of what you configure. What TLS doesn't do is keep the message or file content unreadable to PubNub's own servers, which need to read a payload to route it. Most applications don't need more than that. Add message and file encryption on top only when a compliance obligation or a threat model requires that PubNub itself never see plaintext.

The CryptoModule is the mechanism for that. All clients that send and receive encrypted content must configure the SDK with the same cipher key. PubNub servers handle only ciphertext and never store cipher keys. That property cuts both ways. A client without the correct cipher key receives unreadable content, and so do you, if every copy of the key is lost.

Losing a cipher key doesn't just risk a leak. It destroys access to every message and file encrypted with it, including whatever is sitting in Message Persistence. Back up your cipher key with the same care you'd give the data it protects.

Two scopes are available depending on how much of your traffic needs it. Register a CryptoModule at SDK initialization to encrypt everything the client sends and receives on that keyset. Or create a standalone instance to encrypt selected messages or fields, such as a sensitive value inside a payload that otherwise stays in clear text. Refer to Data security and encryption for both. That page also covers how the current AES-CBC 256-bit module stays backward-compatible with content encrypted under the legacy 128-bit one.

Make every administrative change traceable​

Token issuance and key rotation both depend on decisions made in the Admin Portal. Who can enable Access Manager, who can rotate a secret key, who can add a role to your organization: all of these are administrative changes, not code changes. The audit log records each one, who performed it, and when, across the Admin Portal UI, the Admin API, and OAuth integrations.

If a client starts behaving unexpectedly, either suddenly denied access or unexpectedly permitted, check the audit log first. It shows whether a keyset setting, a role, or a secret key changed underneath it. Pair the log with Invite organization members to limit who can make those changes in the first place. A small set of people who could have made an unexpected change is one you can actually check.

Next steps​

Was this page useful?

Last updated on