---
source_url: https://www.pubnub.com/docs/security/access-control/change-or-extend-access
title: Change or extend access
updated_at: 2026-09-30T07:20:08.000Z
---

# Change or extend access

> For AI agents: documentation index at https://www.pubnub.com/llms-full.txt

Use this page to update what a user can access (change permissions) or to keep their session alive by refreshing a token before it expires (extend access).

## Before you start

Confirm you have:

* A server-side PubNub instance initialized with a `secretKey`. See [Initialize a server SDK with a secret key](https://www.pubnub.com/docs/security/access-control/initialize-server-sdk.md).
* Clients initialized with an `authKey`. See [Initialize a client SDK with an auth key](https://www.pubnub.com/docs/security/access-control/initialize-client-sdk.md).

## Change a user's permissions

To add or remove a user's access to resources, grant a new token with the updated resource list and return it to the client.

1. On your server, call `grantToken` with the updated resources for the user. See [Grant, change, and revoke permissions](https://www.pubnub.com/docs/security/access-control/manage-permissions.md#grant-a-token).
2. Return the new token to the client.
3. On the client, call `setToken` with the new token. See [Initialize a client SDK with an auth key](https://www.pubnub.com/docs/security/access-control/initialize-client-sdk.md#update-the-token-after-initialization).

The client uses the new token on its next request. The old token remains valid until its TTL expires or you revoke it.

## Extend access before a token expires

To keep a user's session active, refresh the token before it expires. The core approach is the same as changing permissions: grant a new token and push it to the client. Three strategies for when and how to do this are listed below.

### Strategy 1: Server-side proactive refresh

The server tracks the expiry time of each token it issues. Before a token expires, the server requests a new grant and pushes the token to the client. The client sets the new token when it receives it.

Best for: apps where the server has a persistent connection to clients (for example, via a WebSocket or PubNub channel).

### Strategy 2: Client-side TTL timer

The client calculates when the token expires from the `timestamp` and `ttl` fields returned by `parseToken`, and sets a timer to request a refresh before that time. When the timer fires, the client calls your server's token refresh endpoint. The server grants a new token and returns it. The client sets it with `setToken`.

Best for: apps where the client drives the session lifecycle.

```javascript
const REFRESH_BUFFER_MS = 60 * 1000;
const MAX_RETRY_DELAY_MS = 60 * 1000;
const MAX_TIMER_DELAY_MS = 2 ** 31 - 1;

let currentToken = null;
let refreshTimer = null;
let refreshInFlight = null;
let retryDelayMs = 1000;

function scheduleTokenRefresh(token) {
  currentToken = token;
  clearTimeout(refreshTimer);

  // timestamp is the issue time in Unix seconds; ttl is in minutes.
  const { timestamp, ttl } = pubnub.parseToken(token);
  const expiresAt = (timestamp + ttl * 60) * 1000;
  const bufferMs = Math.min(REFRESH_BUFFER_MS, (ttl * 60 * 1000) / 2);
  const delay = expiresAt - Date.now() - bufferMs;

  if (delay > MAX_TIMER_DELAY_MS) {
    refreshTimer = setTimeout(() => scheduleTokenRefresh(token), MAX_TIMER_DELAY_MS);
    return;
  }
  refreshTimer = setTimeout(refreshToken, Math.max(delay, 0));
}

function refreshToken() {
  if (refreshInFlight) return refreshInFlight;

  refreshInFlight = fetchTokenFromYourServer()
    .then((newToken) => {
      retryDelayMs = 1000;
      pubnub.setToken(newToken);
      scheduleTokenRefresh(newToken);
    })
    .catch((error) => {
      console.error('Token refresh failed, retrying:', error);
      clearTimeout(refreshTimer);
      refreshTimer = setTimeout(refreshToken, retryDelayMs);
      retryDelayMs = Math.min(retryDelayMs * 2, MAX_RETRY_DELAY_MS);
    })
    .finally(() => {
      refreshInFlight = null;
    });

  return refreshInFlight;
}

// Browsers delay or pause timers in hidden tabs and on sleeping devices.
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible' && currentToken) {
    scheduleTokenRefresh(currentToken);
  }
});

scheduleTokenRefresh(initialToken);
```

Adapt `fetchTokenFromYourServer()` to your server's token API. The example behaves as follows:

* **Expiry time.** A token expires `ttl` minutes after `timestamp`, not `ttl` minutes after the client receives it. `timestamp` is in Unix seconds and `ttl` is in minutes, so `(timestamp + ttl * 60) * 1000` gives the expiry time in milliseconds, the unit `Date.now()` uses.
* **Buffer.** The refresh starts `REFRESH_BUFFER_MS` before expiry, or at half the token's lifetime for tokens shorter than twice the buffer. `timestamp` comes from PubNub, while `Date.now()` comes from the device clock, so clock skew between the two shifts the refresh time. If device clocks in your audience can be off by more than a few seconds, increase the buffer to cover that skew and the time your refresh request takes.
* **Overdue tokens.** If the token is already past its refresh time, for example because the app loaded a stored token, the refresh starts immediately.
* **Resume.** When the tab becomes visible again, the client recalculates the delay from the current time, so a timer that the browser paused doesn't fire late. In React Native or other non-browser clients, call `scheduleTokenRefresh(currentToken)` from your app's resume event instead of `visibilitychange`.
* **One refresh at a time.** `refreshInFlight` holds the pending request, so a resume event during a refresh doesn't start a second one.
* **Errors.** A failed refresh retries with exponential backoff, capped at `MAX_RETRY_DELAY_MS`. The client keeps its current token until a refresh succeeds.
* **Long-lived tokens.** `setTimeout` can't wait longer than `MAX_TIMER_DELAY_MS` (about 24.8 days), so the example re-checks at that interval for tokens with a longer lifetime.

### Strategy 3: Just-in-time on 403

The client handles `403` responses by requesting a new token from the server, setting it with `setToken`, calling `reconnect()`, and retrying the failed request.

Best for: simpler apps where occasional brief access interruptions are acceptable. This strategy reacts to failures rather than preventing them.

:::warning Reconnect after setting a token
When you set a new token after receiving a `403`, call `pubnub.reconnect()` (name may vary across SDKs) before retrying the request. Without reconnecting, the SDK may continue using the expired or revoked token.
:::

## Related pages

* [Grant, change, and revoke permissions](https://www.pubnub.com/docs/security/access-control/manage-permissions.md). Call `grantToken` from your server.
* [Initialize a client SDK with an auth key](https://www.pubnub.com/docs/security/access-control/initialize-client-sdk.md). Call `setToken` on the client.
* [Update an expired token](https://www.pubnub.com/docs/security/access-control/update-expired-token.md). Steps for handling a token that has already expired.

Last updated at: 2026-09-30T07:20:08.000Z
