---
source_url: https://www.pubnub.com/docs/general/security/access-control
title: Access control and permissions management
updated_at: 2026-05-19T06:04:41.751Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Access control and permissions management

:::warning Access Manager v2 is deprecated
This documentation describes Access Manager v3.
If you use Access Manager in v2, [migrate](https://www.pubnub.com/docs/general/resources/migration-guides/pam-v3-migration) to the latest version (v3).
:::

Access Manager is an optional add-on that lets you control who can read from or write to your PubNub channels and user metadata. Without it, any client with your keys has unrestricted access to all resources on that keyset.

Access Manager (v3) is a token‑based access control system for PubNub resources: channels, channel groups, and user IDs. You can make a 1:1 chat private by allowing only two users to read and write. You can also make a channel public by granting access to all users. You can define many permissions in one API call by listing resources or using regular‑expression patterns.

:::note User ID / UUID
User ID is also referred to as **UUID/uuid** in some APIs and server responses but **holds the value** of the **userId** parameter you [set during initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id).
:::

:::tip Access Manager is optional but recommended
Access Manager is an **optional** add-on you enable per keyset in the [Admin Portal](https://admin.pubnub.com/). It's not enabled by default.
Without Access Manager, PubNub resources on this keyset have no access controls. Any client that connects can reach channels and metadata without permission checks.
Enable Access Manager when your app requires:
* Private or restricted channels, such as 1:1 chat, group DMs, or member-only spaces.
* User-scoped permissions, to bind tokens to a specific User ID so only that user can consume them.
* Sensitive data handling, any channel carrying personal, financial, or health information.
* Regulatory compliance, HIPAA, SOC 2, GDPR, or similar requirements that mandate access control.
If your app streams public, non-sensitive data with no user authentication (for example, a live sports scoreboard), you may not need Access Manager. For all other production scenarios, enabling it is strongly recommended.
:::

Apps that use Access Manager create user tokens with individual permissions. PubNub generates these tokens. The client gets a token from your server and sends it with each PubNub API request.

:::warning Accepted tokens
Access Manager uses PubNub‑generated cryptographic tokens to define permissions for channels, groups, and metadata. External tokens (such as JWTs) aren’t supported.
:::

## Configuration

Enable Access Manager for your app’s keyset in the [Admin Portal](https://admin.pubnub.com/).

:::tip Public Admin Portal demo
Want to browse through the Admin Portal without creating an account? Explore it through the [Public Demo](https://demo-admin.pubnub.com/) that shows examples of most PubNub features for transport and logistics use case.
:::

![Access Manager in Admin Portal](https://www.pubnub.com/assets/images/access-manager-c53bde865330e247386a6f847a4d738e.png)

| Option | Description |
| --- | --- |
| **Revoke v3 Token** | [Invalidate](https://www.pubnub.com/docs/general/security/access-control#revoke-permissions) a token so it can’t authenticate access to PubNub resources. |

## Authorization flow

Three actors participate in the authorization process:

* Server - A centralized server manages access. Only the server can request grants with the secretKey. Expose an API so clients can get new or updated tokens. Use the server to validate logins, set permissions, and specify the authorized_uuid.
* Client device - A client runs on one device. It requests a token from the server, sets it as the authKey, and uses it for API calls to channels, channel groups, and user ID metadata. The client refreshes the token before it expires.
* PubNub - PubNub provides APIs for both servers and clients. Servers call the grant API to generate or refresh tokens. Clients pass tokens with requests (publish, subscribe). PubNub validates that the user has the required permissions.

A typical client authorization could look as follows:

![Client Devices → Your Server → PN Network ← Client Devices](https://www.pubnub.com/assets/images/pam-v3-authorization-flow-d3c28108b6948645d029e42097d1b30e.png)

1. Upon login, the client requests authorization.
2. The server uses the secretKey to request a token with the needed permissions for the authorized User ID.
3. PubNub returns a signed, time‑limited token.
4. The server returns the token to the client.
5. The client sets the token (the authKey) in the SDK configuration.
6. The client uses the token for API calls until it expires or is revoked, then requests a new token.

This flow ensures only authorized users access specific PubNub resources.

## Server-side operations

Once your server can grant tokens, clients use those tokens securely.

Use a centralized server that initializes a server‑side PubNub SDK with a `secretKey`. Only the server can request permission grants.

### Initialize with a secret key

The `secretKey` lets you give clients access to PubNub resources, change access levels, and remove permissions. When you initialize PubNub with the `secretKey`, you get root permissions for Access Manager. Servers get `read` and `write` access to all resources, so you do not need to grant extra access for server calls.

[Paid](https://www.pubnub.com/pricing/) plans support [secret key rotation](https://www.pubnub.com/docs/portal/keysets#secret-key-rotation). It manages and expires up to five keys, including the current key.

:::warning Secret key security
Use the `secretKey` only on a secure server. Never expose it to client devices. If it is compromised, regenerate it in the [Admin Portal](https://admin.pubnub.com/).
:::

###### Node.js

```javascript
const pubnub = new PubNub({
    subscribeKey: "mySubscribeKey",
    publishKey: "myPublishKey",
    secretKey: "mySecretKey",
    userId: "myUniqueUserId"
  });
```

###### Python

```python
pn_config = PNConfiguration()
pn_config.subscribe_key = "my_subscribe_key"
pn_config.publish_key = "my_publish_key"
pn_config.secret_key = "my_secret_key"
pn_config.user_id = "my_unique_user_id"
pubnub = PubNub(pn_config)
```

###### Java

```java
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "yourSubscribeKey");
// publishKey from Admin Portal (only required if publishing)
configBuilder.publishKey("PublishKey");
configBuilder.secretKey("mySecretKey");
PubNub pubNub = PubNub.create(configBuilder.build());
```

###### Kotlin

```kotlin
val pnConfiguration = PNConfiguration(UserId("myUserId")).apply {
    subscribeKey = "my_subkey"
    publishKey = "my_pubkey"
    secretKey = "my_secretkey"
    secure = true
  }
```

###### Go

```go
pnconfig := pubnub.NewConfig()
  pnconfig.SubscribeKey = "MySubscribeKey"
  pnconfig.PublishKey = "MyPublishKey"
  pnconfig.SecretKey = "MySecretKey"
  pnconfig.SetUserId(UserId("myUniqueUserId"))
  pn := pubnub.NewPubNub(pnconfig)
```

###### C#

```csharp
PNConfiguration pnconfig = new PNConfiguration();
pnconfig.SubscribeKey = "mySubscribeKey";
pnconfig.PublishKey = "myPublishKey";
pnconfig.SecretKey = "mySecretKey";
pnconfig.UserId = "MyUniqueUserId";
Pubnub pubnub = new Pubnub(pnconfig);
```

###### Dart

```dart
final myKeyset = Keyset(
  subscribeKey: 'mySubscribeKey',
  publishKey: 'myPublishKey',
  secretKey: 'mySecretKey',
  userId: UserId('yourUniqueUserId')
  );
```

###### PHP

```php
use PubNub\PNConfiguration;
$pnConfiguration = new PNConfiguration();
$pnConfiguration->setSubscribeKey("MySubscribeKey");
$pnConfiguration->setPublishKey("MyPublishKey");
$pnConfiguration->setSecretKey("MySecretKey");
$pnConfiguration->setUserId("MyUniqueUserId");
```

###### Ruby

```ruby
pubnub = Pubnub.new(
    subscribe_key: 'my_subscribe_key',
    publish_key: 'my_publish_key',
    secret_key: 'my_secret_key',
    user_id: 'myUniqueUserId'
);
```

### Grant permissions

PubNub enforces access with time‑limited grant tokens.

After you enable Access Manager, call PubNub to grant a token. Specify the authorized User ID, the resource permissions (lists or RegEx), and the `ttl` (Time To Live).

An authorized User ID can have permissions for:

* Channels
* Channel groups
* User IDs (which are other users' object metadata, such as their names or avatars)

Once the grant is successful, the server responds to the client device's authentication request by returning a token with embedded permissions.

The code below grants the `my-authorized-uuid`:

* Read access to `channel-a`, `channel-group-b`, and `uuid-c`.
* Read/write access to `channel-b`, `channel-c`, `channel-d`, and `uuid-d`.
* Read access to all channels that match the `channel-[A-Za-z0-9]` RegEx pattern.

#### Node.js

```javascript
pubnub.grantToken(
    {
        ttl: 15,
        authorized_uuid: "my-authorized-uuid",
        resources: {
            channels: {
                "channel-a": {
                    read: true
                },
               "channel-b": {
                    read: true,
                    write: true
                },
               "channel-c": {
                    read: true,
                    write: true
                },
               "channel-d": {
                    read: true,
                    write: true
                }
            },
            groups: {
                "channel-group-b": {
                    read: true
                }
            },
            uuids: {
                "uuid-c": {
                    get: true
                },
                "uuid-d": {
                    get: true,
                    update: true
                }
            }
        },
        patterns: {
          channels: {
            "^channel-[A-Za-z0-9]$": {
                read: true
            }
          }
        }
    },
    function (status, token) {
        console.log(token)
    });
```

#### Python

```python
from pubnub.models.consumer.v3.channel import Channel
from pubnub.models.consumer.v3.group import Group
from pubnub.models.consumer.v3.uuid import UUID

channels = [
    Channel.id("channel-a").read(),
    Channel.pattern("channel-[A-Za-z0-9]").read(),
    Channel.id("channel-b").read().write(),
    Channel.id("channel-c").read().write(),
    Channel.id("channel-d").read().write()
]
channel_groups = [
    Group.id("channel-group-b").read()
]
uuids = [
    UUID.id("uuid-c").get(),
    UUID.id("uuid-d").get().update()
]
envelope = pubnub.grant_token() \
    .authorized_uuid("my-authorized-uuid") \
    .channels(channels) \
    .groups(channel_groups) \
    .uuids(uuids) \
    .ttl(15) \
    .sync()

token = envelope.result.token
```

#### Java

```java
pubnub.grantToken()
    .ttl(15)
    .authorizedUUID("my-authorized-uuid")
        .channels(Arrays.asList(
                ChannelGrant.name("channel-a").read(),
                ChannelGrant.name("channel-b").read().write(),
                ChannelGrant.name("channel-c").read().write(),
                ChannelGrant.name("channel-d").read().write(),
                ChannelGrant.pattern("^channel-[A-Za-z0-9]*$").read()))
        .channelGroups(Collections.singletonList(
                ChannelGroupGrant.id("channel-group-b").read()))
        .uuids(Arrays.asList(
                UUIDGrant.id("uuid-c").get(),
                UUIDGrant.id("uuid-d").get().update()))
        .async(result -> { /* check result */ });
```

#### Kotlin

```kotlin
pubnub.grantToken(
    ttl = 15,
    authorizedUUID = "my-authorized-uuid",
    channels = listOf(
        ChannelGrant.name(name = "channel-a", read = true),
        ChannelGrant.name(name = "channel-b", read = true, write = true),
        ChannelGrant.name(name = "channel-c", read = true, write = true),
        ChannelGrant.name(name = "channel-d", read = true, write = true),
        ChannelGrant.pattern(pattern = "^channel-[A-Za-z0-9]*$", read = true)
    ),
    channelGroups = listOf(
        ChannelGroupGrant.id(id = "channel-group-b", read = true)
    ),
    uuids = listOf(
        UUIDGrant.id(id = "uuid-c", get = true),
        UUIDGrant.id(id = "uuid-d", get = true, update = true)
    )
)
    .sync()
```

#### Go

```go
res, status, err := pn.GrantToken().
        TTL(15).
        AuthorizedUUID("my-authorized-uuid").
        Channels(map[string]pubnub.ChannelPermissions{
                "channel-a": {
                        Read: true,
                },
                "channel-b": {
                        Read: true,
                        Write: true,
                },
                "channel-c": {
                        Read: true,
                        Write: true,
                },
                "channel-d": {
                        Read: true,
                        Write: true,
                },
        }).
        ChannelGroups(map[string]pubnub.GroupPermissions{
                "channel-group-b": {
                        Read: true
                },
        }).
        UUIDs(map[string]pubnub.UUIDPermissions{
                "uuid-c": {
                        Get: true,
                },
                "uuid-d": {
                        Get: true,
                        Update: true,
                },
        }).
        ChannelsPattern(map[string]pubnub.ChannelPermissions{
                "^channel-[A-Za-z0-9]*$": {
                        Read: true,
                },
        }).
        Execute()
```

#### C

```c
char* author_uuid = "my-authorized-uuid";
struct pam_permission cha_perm = {.read=true };
struct pam_permission cgb_perm = {.read=true };
struct pam_permission uidc_perm = {.get=true };

struct pam_permission chb_perm = {.read=true, .write=true };
struct pam_permission chc_perm = {.read=true, .write=true };
struct pam_permission chd_perm = {.read=true, .write=true };
struct pam_permission uidd_perm = {.get=true, .update=true };

struct pam_permission pat_ch_perm = {.read=true };

int perm_cha = pubnub_get_grant_bit_mask_value(cha_perm);
int perm_chb = pubnub_get_grant_bit_mask_value(chb_perm);
int perm_chc = pubnub_get_grant_bit_mask_value(chc_perm);
int perm_chd = pubnub_get_grant_bit_mask_value(chd_perm);

int perm_cgb = pubnub_get_grant_bit_mask_value(cgb_perm);

int perm_uidc = pubnub_get_grant_bit_mask_value(uidc_perm);
int perm_uidd = pubnub_get_grant_bit_mask_value(uidd_perm);

int perm_ch_pat = pubnub_get_grant_bit_mask_value(pat_ch_perm);

int ttl_minutes = 15;
char perm_obj[2000];
sprintf(perm_obj,"{\"ttl\":%d, \"uuid\":\"%s\", \"permissions\":{\"resources\":{\"channels\":{ \"channel-a\":%d, \"channel-b\":%d, \"channel-c\":%d, \"channel-d\":%d }, \"groups\":{ \"channel-group-b\":%d }, \"uuids\":{ \"uuid-c\":%d, \"uuid-d\":%d }}, \"patterns\":{\"channels\":{ \"channel-[A-Za-z0-9]\":%d }, \"groups\":{ }, \"uuids\":{ }},\"meta\":{ }}}", ttl_minutes, author_uuid, perm_cha, perm_chb, perm_chc, perm_chd, perm_cgb, perm_uidc, perm_uidd, perm_ch_pat);
res = pubnub_grant_token(gtp, perm_obj);
if (PNR_STARTED == res) {
res = pubnub_await(gtp);
if (PNR_OK == res) {
    pubnub_chamebl_t grant_token_resp = pubnub_get_grant_token(gtp);
    printf("pubnub_grant_token() Response from Pubnub: %s\n", grant_token_resp.ptr);
}
}
```

#### C#

```csharp
PNResult<PNAccessManagerTokenResult> grantTokenResponse = await pubnub.GrantToken()
    .TTL(15)
    .AuthorizedUuid("my-authorized-uuid")
    .Resources(new PNTokenResources()
    {
        Channels = new Dictionary<string, PNTokenAuthValues>() {
            { "channel-a", new PNTokenAuthValues() { Read = true } },
            { "channel-b", new PNTokenAuthValues() { Read = true, Write = true } },
            { "channel-c", new PNTokenAuthValues() { Read = true, Write = true } },
            { "channel-d", new PNTokenAuthValues() { Read = true, Write = true } }},
        ChannelGroups = new Dictionary<string, PNTokenAuthValues>() {
            { "channel-group-b", new PNTokenAuthValues() { Read = true } } },
        Uuids = new Dictionary<string, PNTokenAuthValues>() {
            { "uuid-c", new PNTokenAuthValues() { Get = true } },
            { "uuid-d", new PNTokenAuthValues() { Get = true, Update = true } }}
    })
    .Patterns(new PNTokenPatterns()
    {
        Channels = new Dictionary<string, PNTokenAuthValues>() {
            { "channel-[A-Za-z0-9]", new PNTokenAuthValues() { Read = true } }}
    })
    .ExecuteAsync();
PNAccessManagerTokenResult grantTokenResult = grantTokenResponse.Result;
PNStatus grantTokenStatus = grantTokenResponse.Status;
if (!grantTokenStatus.Error && grantTokenResult != null)
{
    Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(grantTokenResult));
}
else
{
    Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(grantTokenStatus));
}
```

#### Dart

```dart
var request = pubnub.requestToken(
    ttl: 15, authorizedUUID: 'my-authorized-uuid')
..add(ResourceType.channel, name: 'channel-a', read: true)
..add(ResourceType.channelGroup, name: 'channel-group-b', read: true)
..add(ResourceType.uuid, name: 'uuid-c', get: true)
..add(ResourceType.channel, name: 'channel-b', read: true, write: true)
..add(ResourceType.channel, name: 'channel-c', read: true, write: true)
..add(ResourceType.channel, name: 'channel-d', read: true, write: true)
..add(ResourceType.uuid, name: 'uuid-d', get: true, update: true)
..add(ResourceType.channel, pattern: 'channel-[A-Za-z0-9]', read: true);

var token = await pubnub.grantToken(request);
print('grant token = $token');
```

#### PHP

```php
$pubnub->grantToken()
    ->ttl(15)
    ->authorizedUuid('my-authorized-uuid')
    ->addChannelResources([
        'channel-a' => ['read' => true],
        'channel-b' => ['read' => true, 'write' => true],
        'channel-c' => ['read' => true, 'write' => true],
        'channel-d' => ['read' => true, 'write' => true],
    ])
    ->addChannelGroupResources([
        'channel-group-b' => ['read' => true],
    ])
    ->addUuidResources([
        'uuid-c' => ['get' => true],
        'uuid-d' => ['get' => true, 'update' => true],
    ])
    ->addChannelPatterns([
        '^channel-[A-Za-z0-9]$' => ['read' => true],
    ])
```

#### Ruby

```ruby
pubnub.grant_token(
        ttl: 15,
        authorized_uuid: "my-authorized-uuid",
        channels: {
            "channel-a": Pubnub::Permissions.res(
                read: true
            ),
            "channel-b": Pubnub::Permissions.res(
                read: true,
                write: true
            ),
            "channel-c": Pubnub::Permissions.res(
                read: true,
                write: true
            ),
            "channel-d": Pubnub::Permissions.res(
                read: true,
                write: true
            ),
            "^channel-[A-Za-z0-9]$": Pubnub::Permission.pat(
                read: true
            )
        },
        channel_groups: {
            "channel-group-b": Pubnub::Permissions.res(
                read: true
            )
        },
        uuids: {
            "uuid-c": Pubnub::Permissions.res(
                get: true
            ),
            "uuid-d": Pubnub::Permissions.res(
                get: true,
                update: true
            )
        },
        http_sync: true
    );
```

#### Token size limits

A token stores all access mappings. As you add permissions, the token grows. Larger tokens increase HTTP request size.

Requests that exceed 32 KiB fail with `414 URI Too Long`. To stay within limits:

* Prefer RegEx patterns over long resource lists.
* Keep resource names short and consistent.

See [channel naming convention](https://www.pubnub.com/docs/general/channels/channel-naming#recommended-naming-convention) or [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com) for help.

#### TTL

`ttl` is the number of minutes before granted permissions expire. It is required for every grant. There is no default.

The minimum is `1` (1 minute). The maximum is `43200` (30 days). If you need a higher limit, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

#### RegEx

You can grant access in a single API call. Use either:

* A single resource or a list of resources the authorized UUID can access.
* A pattern‑based sequence of UUIDs, channels, or channel groups using regular expressions.

Pattern matching for `patterns` is evaluated on the PubNub server (not by the SDK). Supported syntax is based on [RE2](https://github.com/google/re2/wiki/Syntax): backreferences and lookaround assertions are not supported.

To succeed, specify permissions for at least one UUID, channel, or channel group (resource list or pattern).

#### Authorized UUID

For a higher level of security, you can specify one top-level authorized UUID in the grant payload. When specified, this UUID will be embedded in the token and returned by the grant request. This ensures that any request to PubNub that uses that token has to come from that authorized UUID. Otherwise, PubNub will reject the request and deny access to the resources.

:::note Authorized UUID vs UUIDs
The grant request body contains the `uuids` key which defines permissions required to access the other UUIDs' (users') metadata. The UUIDs contained within have nothing to do with the UUID authorized to use the token. To allow a UUID to use a particular token, specify this UUID as an authorized one (`authorized_uuid`). The value of that parameter must be an instance of a preexisting client's UUID that was set during the initialization of its PubNub object. For more information about setting UUIDs, refer to [Identity Management](https://www.pubnub.com/docs/general/setup/users-and-devices#user-id-usage).
:::

###### Manage the User IDs that tokens authorize

The `authorized_uuid` must match an existing client's User ID set during [PubNub initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id). Plan your User ID strategy before designing token grants. Each User ID should be stable, reusable, and non-personally-identifiable to support both secure token binding and accurate billing.

### Change permissions

Apps often change a user's permissions. For example, add or remove a user from a channel. The server requests a new grant and returns the token to the client.

### Revoke permissions

:::note Enable token revoke
To revoke tokens, you must first enable this feature on the [Admin Portal](https://admin.pubnub.com/). To do that, navigate to your app's keyset and mark the *Revoke v3 Token* checkbox in the *ACCESS MANAGER* section.
:::

Access Manager lets you revoke a token. Calls that use a revoked token fail with a `403 Revoked Token` error. Revoking tokens is useful when you need to remove access quickly.

You can only revoke a valid token previously obtained through a [token grant](#grant-permissions) request. Each revoked token is stored in a *deny list* (usual charges apply) allowing for quick lookup of revoked tokens.

Consider these constraints when revoking tokens:

* You can only enable the token revoke feature if the token `ttl` for the subkey is less than or equal to 30 days. If that `ttl` value doesn't meet your requirements, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).
* If support changes your token's `ttl` to exceed 30 days, you can disable the token revoke functionality, but can't re-enable it using the [Admin Portal](https://admin.pubnub.com/). To do that, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).
* You can only revoke one token per one revoke call, batch revokes aren't supported.
* It may take up to 1 minute for the token revoke request to take effect.
* You can't re-enable a revoked token.

###### Node.js

```javascript
const token = await pubnub.revokeToken("p0AkFl043rhDdHRsple3KgQ3NwY6BDcENnctokenVzcqBDczaWdYIGOAeTyWGJI");
```

###### Python

```python
envelope = pubnub.revoke_token("p0thisAkFl043rhDdHRsCkNyZXisRGNoYW6hanNlY3JldAFDZ3Jwsample3KgQ3NwY6BDcGF0pERjaGFuoENnctokenV")
    .sync()
```

###### Java

```java
pubnub.revokeToken()
    .token("p0thisAkFl043rhDdHRsCkNyZXisRGNoYW6hanNlY3JldAFDZ3Jwsample3KgQ3NwY6BDcGF0pERjaGFuoENnctokenV")
    .sync()
```

###### Kotlin

```kotlin
pubnub.revokeToken("p0thisAkFl043rhDdHRsCkNyZXisRGNoYW6hanNlY3JldAFDZ3Jwsample3KgQ3NwY6BDcGF0pERjaGFuoENnctokenV")
    .sync()
```

###### Go

```go
res, status, err := pn.RevokeToken()
    .Token("p0thisAkFl043rhDdHRsCNlY3JldAFDZ3Jwsample3KgQ3NwY6BDENnctokenV")
    .Execute()
```

###### C#

```csharp
PNResult<PNAccessManagerRevokeTokenResult> revokeTokenResponse = await pubnub
    .RevokeToken()
    .Token("p0thisAkFl043rhDdHRsCkNyZXisRGNoYW6hanNlY3JldAFDZ3Jwsample3KgQ3NwY6BDcGF0pERjaGFuoENnctokenV")
    .ExecuteAsync();
PNAccessManagerRevokeTokenResult revokeTokenResult = revokeTokenResponse.Result;
PNStatus revokeTokenStatus = revokeTokenResponse.Status;
if (!revokeTokenStatus.Error && revokeTokenResult != null)
{
    Console.WriteLine("Revoke token success");
}
else
{
    Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(revokeTokenStatus));
}
```

###### Dart

```dart
await pubnub.revokeToken("p0AkFl043rhDdHRsple3KgQ3NwY6BDcENnctokenVzcqBDczaWdYIGOAeTyWGJI");
```

###### PHP

```php
$pubnub->revokeToken("p0thisAkFl043rhDdHRsCkNyZXisRGNoYW6hanNlY3JldAFDZ3Jwsample3KgQ3NwY6BDcGF0pERjaGFuoENnctokenV")
    ->sync();
```

###### Ruby

```ruby
pubnub.revoke_token(token: "p0thisAkFl043rhDdHRsCkNyZXisRGNoYW6hanNlY3JldAFDZ3Jwsample3KgQ3NwY6BDcGF0pERjaGFuoENnctokenV", http_sync: true)
```

#### Token caching

PubNub caches tokens for performance. If a token isn’t in the deny list, PubNub caches that state for up to one minute.

If the token was found in the deny list, the system will cache this response for the `ttl` of the token.

## Client-side operations

After the server grants tokens, clients use them as follows.

In general, client applications don't generate tokens, but rather request tokens from server APIs, which handle authentication and permissions logic. The syntax and implementation of these client and server APIs are up to the developer. This section outlines operations that a client may take after getting a token from the centralized server applications.

### Initialize with an authKey

When a user logs in, the client sends data to the server. The server validates identity, determines permissions, and specifies the authorized UUID. It generates a token using the `secretKey` and receives the token (`authKey`) from PubNub. The server returns the token to the client.

To securely configure client-side access, use the token received from your server. This key ensures clients have the necessary permissions without exposing sensitive information like the `secretKey`.

Here's how to set up the client SDK with the token:

#### JavaScript

```javascript
const pubnub = new PubNub({
  subscribeKey: "mySubscribeKey",
  publishKey: "myPublishKey",
  userId: "myUniqueUserId",
  authKey: "yourAuthKey" // Include the authKey here
});
```

#### Python

```python
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub

pnconfig = PNConfiguration()
pnconfig.subscribe_key = "my_subscribe_key"
pnconfig.publish_key = "my_publish_key"
pnconfig.user_id = "my_unique_user_id"
pnconfig.auth_key = "your_auth_key"  # Include the authKey here
pnconfig.ssl = True

pubnub = PubNub(pnconfig)
```

#### Swift

```swift
```swift
import PubNub

let config = PubNubConfiguration(
  publishKey: "myPublishKey",
  subscribeKey: "mySubscribeKey",
  userId: "myUniqueUserId",
  authKey: "yourAuthKey"  // Include the authKey here
)

let pubnub = PubNub(configuration: config)
```

#### Objective-C

```objectivec
#import <PubNub/PubNub.h>

// Set up the PubNub configuration
PNConfiguration *config = [PNConfiguration configurationWithPublishKey:@"myPublishKey"
                                                           subscribeKey:@"mySubscribeKey"
                                                                 userID:@"myUniqueUserId"];
config.authKey = @"yourAuthKey"; // Include the authKey here

// Initialize the PubNub client
self.client = [PubNub clientWithConfiguration:config];
```

#### Go

```go
package main

import pubnub "github.com/pubnub/go"

func main() {
    config := pubnub.NewConfigWithUserId("myUniqueUserId")
    config.SubscribeKey = "mySubscribeKey"
    config.PublishKey = "myPublishKey"
    config.AuthKey = "yourAuthKey" // Include the authKey here
    config.Secure = true

    pn := pubnub.NewPubNub(config)
    // Now you can use `pn` to interact with PubNub services
}
```

#### Unity

```csharp
using PubnubApi;

public class PubNubSetup
{
    public void InitializePubNub()
    {
        // Initialize the PNConfiguration with a unique UserId
        PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"));
        
        // Set the SubscribeKey and PublishKey from Admin Portal
        pnConfiguration.SubscribeKey = "mySubscribeKey";
        pnConfiguration.PublishKey = "myPublishKey";
        
        // Include the AuthKey here
        pnConfiguration.AuthKey = "yourAuthKey";
        
        // Use SSL
        pnConfiguration.Secure = true;
        
        // Initialize the PubNub instance
        Pubnub pubnub = new Pubnub(pnConfiguration);

        // You can now use `pubnub` to interact with PubNub services
    }
}
```

#### C#

```csharp
using PubnubApi;

public class PubNubSetup
{
    public void InitializePubNub()
    {
        // Initialize the PNConfiguration with a unique UserId
        PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"));
        
        // Set the SubscribeKey and PublishKey from Admin Portal
        pnConfiguration.SubscribeKey = "mySubscribeKey";
        pnConfiguration.PublishKey = "myPublishKey";
        
        // Include the AuthKey here
        pnConfiguration.AuthKey = "yourAuthKey";
        
        // Use SSL
        pnConfiguration.Secure = true;
        
        // Initialize the PubNub instance
        Pubnub pubnub = new Pubnub(pnConfiguration);

        // You can now use `pubnub` to interact with PubNub services
    }
}
```

#### Dart

```dart
import 'package:pubnub/pubnub.dart';

void main() {
  // Create a keyset with the required parameters
  final myKeyset = Keyset(
    subscribeKey: 'mySubscribeKey',
    publishKey: 'myPublishKey',
    authKey: 'yourAuthKey', // Include the authKey here
    userId: UserId('myUniqueUserId'),
  );

  // Initialize the PubNub instance with the keyset
  final pubnub = PubNub(defaultKeyset: myKeyset);

  // You can now use `pubnub` to interact with PubNub services
}
```

#### PHP

```php
<?php

use PubNub\PNConfiguration;
use PubNub\PubNub;

// Create a PNConfiguration with a unique UserId
$pnConfiguration = new PNConfiguration();
$pnConfiguration->setSubscribeKey("mySubscribeKey");
$pnConfiguration->setPublishKey("myPublishKey");
$pnConfiguration->setUserId("myUniqueUserId");
$pnConfiguration->setAuthKey("yourAuthKey"); // Include your authKey here
$pnConfiguration->setSecure(true); // Use SSL

// Initialize the PubNub instance with the configuration
$pubnub = new PubNub($pnConfiguration);

// You can now use `$pubnub` to interact with PubNub services
```

#### Ruby

```ruby
require 'pubnub'

# Initialize the PubNub client with the necessary parameters
pubnub = Pubnub.new(
    subscribe_key: 'mySubscribeKey',
    publish_key: 'myPublishKey',
    user_id: 'myUniqueUserId',
    auth_key: 'yourAuthKey', # Include your authKey here
    ssl: true # Use SSL
)

# You can now use `pubnub` to interact with PubNub services
```

### Check permissions

Access Manager v3 allows you to decode your permissions by parsing a token. You don't need a `secretKey` to request token details.

Use this method whenever you want to:

* Debug an issue to diagnose the reason for a failing request that returns a `403`.
* Inspect privileges embedded in the token to check if you have access to a given resource.

Request token details:

#### JavaScript

```javascript
pubnub.parseToken("yourToken")
```

#### Python

```python
pubnub.parse_token("your_token")
```

#### Java

```java
pubnub.parseToken("yourToken")
```

#### Kotlin

```kotlin
pubnub.parseToken("yourToken")
```

#### Swift

```swift
pubnub.parse(token: "yourToken")
```

#### Objective-C

```objectivec
PNPAMToken *token = [self.client parseAuthToken:@"yourToken"];
NSLog(@"Token permissions: %@", token);
```

#### Go

```go
pubnub.ParseToken("YourToken") // Given the "pubnub" package is imported: import (pubnub "github.com/pubnub/go/v5")
```

#### C

```c
char* cbor_data = pubnub_parse_token(<pubnub_context>, "yourToken");
```

#### Unity

```csharp
pubnub.ParseToken("yourToken")
```

#### C#

```csharp
pubnub.ParseToken("yourToken")
```

#### Dart

```dart
pubnub.parseToken("yourToken")
```

#### PHP

```php
$pubnub->parseToken("yourToken");
```

#### Ruby

```ruby
pubnub.parse_token("yourToken")
```

See a sample response:

```json
{
   "version":2,
   "timestamp":1629394579,
   "ttl":15,
   "authorized_uuid": "user1",
   "resources":{
      "uuids":{
         "user1":{
            "read":false,
            "write":false,
            "manage":false,
            "delete":false,
            "get":true,
            "update":true,
            "join":false
         }
      },
      "channels":{
         "channel1":{
            "read":true,
            "write":true,
            "manage":false,
            "delete":false,
            "get":false,
            "update":false,
            "join":false
         }
      },
      "groups":{
         "group1":{
            "read":true,
            "write":false,
            "manage":false,
            "delete":false,
            "get":false,
            "update":false,
            "join":false
         }
      }
   },
   "patterns":{
      "uuids":{
         ".*":{
            "read":false,
            "write":false,
            "manage":false,
            "delete":false,
            "get":true,
            "update":false,
            "join":false
         }
      },
      "channels":{
         ".*":{
            "read":true,
            "write":true,
            "manage":false,
            "delete":false,
            "get":false,
            "update":false,
            "join":false
         }
      },
      "groups":{
         ".*":{
            "read":true,
            "write":false,
            "manage":false,
            "delete":false,
            "get":false,
            "update":false,
            "join":false
         }
      }
   }
}
```

### Request a new token

When a client makes an API request using a token that has expired or has been revoked, PubNub API will respond with the `403 Token is expired` or `403 Token revoked` error message. To renew access, the client should include the logic that prompts the server to request a new token to be generated by PubNub. The authorization flow looks similar to the already described [login example](#authorization-flow). In both cases the server first includes the application-specific logic to validate that the request came from an authorized client, and then makes a PubNub token grant request:

![Client Devices → Your Server → PN Network ← Client Devices](https://www.pubnub.com/assets/images/pam-v3-refresh-token-flow-18dbd6cfddde72c31fcedcf058ee1c79.png)

After either a login or a token refresh request from the client, the server passes the newly generated token back to the client device, which then needs to update its configuration and set the new token. Refer to the [Token expiration](#token-expiration) for more information.

#### JavaScript

```javascript
pubnub.setToken("newToken")
```

#### Python

```python
pubnub.set_token("new_token")
```

#### Java

```java
pubnub.setToken("newToken")
```

#### Kotlin

```kotlin
pubnub.setToken("newToken")
```

#### Swift

```swift
pubnub.set(token: "newToken")
```

#### Objective-C

```objectivec
[self.client setAuthToken:@"NewToken"];
```

#### Go

```go
pn.SetToken("NewToken")
```

#### C

```c
pubnub.pubnub_set_token(<pubnub_context>, "NewToken")
```

#### Unity

```csharp
pubnub.SetToken("newToken")
```

#### C#

```csharp
pubnub.SetAuthToken("newToken")
```

#### Dart

```dart
pubnub.setToken("newToken")
```

#### PHP

```php
$pubnub->setToken("newToken");
```

#### Ruby

```ruby
pubnub.set_token("newToken")
```

## Token expiration

PubNub checks the token on every authenticated request. Each token has a `ttl`. When it expires, replace the token.

:::warning Using an expired token
If the client sends an expired token, the PubNub server will return a `403` with a respective error message. When you set a new token, calling [pubnub.reconnect()](https://www.pubnub.com/docs/sdks/javascript/api-reference/misc#reconnect) (name may vary across SDKs) is necessary.
:::

### Update a valid token

To change or extend access to resources, grant a new token with modified permissions.

To address the token expiration effectively, we recommend that you implement one of the following token refresh strategies:

1. The server maintains a list of expiry times, automatically refreshes soon-to-be-stale tokens, and proactively sends the new token to the clients. Clients should respond to these updates by updating the token in the SDK.
2. The client checks the ttl whenever it receives a token and sets a timer to make a refresh request. The server supports a refresh API.
3. The client supports the logic that handles 403 responses, makes a just-in-time token request, updates the SDK upon getting a new token, reconnects, and retries the request that fails.

### Update an expired token

The steps to update a token that is past its `ttl` are similar to updating a valid token with a few exceptions. When your application tries to authenticate using an expired token, PubNub returns an `HTTP 403` error, the request isn't retried automatically, and you must reconnect to PubNub.

To update an expired token, we recommend that your token refresh strategy covers the following steps:

1. The client requests a new token from the server and sets it using the pubnub.setToken() method (name may vary across SDKs).
2. Once the new token is set, the client reconnects to PubNub.
3. The client retries the failed request.

## Permissions

Access Manager v3 grants permissions for these resources. The table lists the allowed flags for each resource:

| Resource | Available Permissions |
| --- | --- |
| Channel | read, write, delete, get, update, manage, join |
| Channel Group | read, manage |
| UUID Metadata | get, update, delete |

###### Scope permissions to channels and channel groups

Channels are the most common resource in Access Manager grants. Each token can include permissions for specific channels by name or for groups of channels via regex patterns. Consistent [channel naming conventions](https://www.pubnub.com/docs/general/channels/channel-naming#naming-consistency) with structured prefixes let you write compact regex grants that scale as you add channels. Channel groups can also be granted `read` and `manage` permissions to control subscription and membership.

### Operations to permissions mapping

The following tables show the mappings of API operations to resources and permissions.

:::tip Chat SDK method to required Access Manager permission mapping
For information about which Chat SDK methods require what Access Manager permissions, refer to [Security and permissions](https://www.pubnub.com/docs/chat/security#operations-to-permissions-mapping).
:::

#### Pub/Sub

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Publish on channel | Channel | Write |
| Signal on channel | Channel | Write |
| Subscribe to channel | Channel | Read |
| Subscribe to presence channel | Presence Channel (`-pnpres`) | Read |
| Subscribe to channel group | Channel Group | Read |
| Subscribe to presence channel group | Presence Channel Group (`-pnpres`) | Read |
| Unsubscribe from channel | Channel | None required |
| Unsubscribe from channel group | Channel Group | None required |

###### Understand the operations behind Pub/Sub permissions

The `write` permission gates the [Publish](https://www.pubnub.com/docs/general/messages/publish#send-messages) and [Signal](https://www.pubnub.com/docs/general/messages/publish#send-signals) operations that send data to a channel. The `read` permission gates [Subscribe](https://www.pubnub.com/docs/general/channels/subscribe), which delivers messages and events to connected clients. Grant both to allow full bidirectional communication on a channel.

#### Presence

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Here Now | Channel | Read |
| Where Now | Channel | None required |
| Get State | Channel | Read |
| Set State | Channel | Read |

###### Understand the operations behind Presence permissions

The `read` permission gates [HereNow](https://www.pubnub.com/docs/general/presence/overview#get-online-users-in-channel) (which queries current channel occupancy), [GetState and SetState](https://www.pubnub.com/docs/general/presence/presence-state) (which manage per-user custom state on a channel), and subscription to presence events on `-pnpres` channels. [WhereNow](https://www.pubnub.com/docs/general/presence/overview#get-subscribed-channels-for-user) is the only presence operation that requires no channel permission because it queries by User ID rather than by channel.

#### Message Persistence

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| History - Fetch Messages | Channel | Read |
| Message Counts | Channel | Read |
| Delete Messages | Channel | Delete |

###### Understand the operations behind Message Persistence permissions

The `read` permission gates [Fetch Messages](https://www.pubnub.com/docs/general/storage#retrieve-messages) and [Message Counts](https://www.pubnub.com/docs/general/storage#get-message-counts), which retrieve and count stored messages on a channel. The `delete` permission gates [Delete Messages](https://www.pubnub.com/docs/general/storage#delete-messages-from-history), allowing selective removal of stored messages. Because these permissions are channel-scoped, you can grant history access to a channel without granting publish or subscribe access.

#### File sharing

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Send file on channel | Channel | Write |
| List files | Channel | Read |
| Download file | Channel | Read |
| Delete file | Channel | Delete |

###### Understand the operations behind File sharing permissions

File operations reuse the same channel-level permissions as messaging. The `write` permission that authorizes [Publish](https://www.pubnub.com/docs/general/messages/publish) also authorizes [Send File](https://www.pubnub.com/docs/general/files#send-files). The `read` permission that authorizes [Subscribe](https://www.pubnub.com/docs/general/channels/subscribe) also authorizes [List Files](https://www.pubnub.com/docs/general/files#list-files) and [Download File](https://www.pubnub.com/docs/general/files#display-and-download-files). The `delete` permission authorizes [Delete File](https://www.pubnub.com/docs/general/files#delete-files). This means a single token grant can cover both messaging and file operations on the same channel.

#### Channel groups

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Add Channels to channel group | Channel Group | Manage |
| Remove Channels from channel group | Channel Group | Manage |
| List Channels in channel group | Channel Group | Read |
| Remove channel group | Channel Group | Manage |

###### Apply channel group permissions to subscription management

Channel group permissions map directly to subscription management operations. The `read` permission lets clients subscribe to all channels in a group and list its membership. The `manage` permission lets your server add or remove channels and delete groups, enabling centralized control over what each client receives. For the full channel group subscription workflow, see [Channel groups](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups).

#### App Context

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Set user metadata | UUID | Update |
| Delete user metadata | UUID | Delete |
| Get user metadata | UUID | Get |
| Get all user metadata | UUID | Managed by the `Disallow Get All User Metadata` option in the [App Context](https://www.pubnub.com/docs/general/metadata/basics#configuration) configuration on the Admin Portal. When this option is unchecked, and Access Manager is enabled in an app, you can get metadata of all users without the need to define that in the permissions schema included in the authentication token. |
| Set channel metadata | Channel | Update |
| Delete channel metadata | Channel | Delete |
| Get channel metadata | Channel | Get |
| Get all channel metadata | Channel | Managed by the `Disallow Get All Channel Metadata` option in the [App Context](https://www.pubnub.com/docs/general/metadata/basics#configuration) configuration on the Admin Portal. When this option is unchecked, and Access Manager is enabled in an app, you can get metadata of all channels without the need to define that in the permissions schema included in the authentication token. |
| Set channel members | Channel | Manage |
| Remove channel members | Channel | Manage |
| Get channel members | Channel | Get |
| Set channel memberships | Channel, UUID | Channels: Join UUID: Update |
| Remove channel memberships | Channel, UUID | Channels: Join UUID: Update |
| Get channel memberships | UUID | Get |

###### Understand the operations behind App Context permissions

App Context uses two resource types in a single token. User metadata operations require UUID-level permissions (`get`, `update`, `delete`), while channel metadata and membership operations require channel-level permissions (`get`, `update`, `delete`, `manage`, `join`). Membership changes require permissions on both the channel and the UUID in the same token. The `Disallow Get All` options in the [Admin Portal configuration](https://www.pubnub.com/docs/general/metadata/basics#configuration) let you control bulk metadata access independently of per-resource grants.

#### Mobile Push Notifications

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Register channel for push | Channel | Read |
| Remove channel's push registration | Channel | Read |

###### Understand the operations behind Mobile Push permissions

Both registering and removing a device from push notifications on a channel require the `read` permission. This means the same `read` grant that allows a client to subscribe to a channel also allows it to manage its own [push notification registrations](https://www.pubnub.com/docs/general/push/send#register-devices) on that channel. No additional permissions are needed for push delivery itself, only for managing which channels trigger push for a device.

#### Message Actions

| PubNub Operation | Resource | Permission |
| --- | --- | --- |
| Add Message Action | Channel | Write |
| Remove Message Action | Channel | Delete |
| Get Message Actions | Channel | Read |
| Get History with Actions | Channel | Read |

## Terms in this document

* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.
