Access Manager v3 API for C SDK

Access Manager v3 lets your servers grant PubNub clients time-limited tokens with embedded permissions, instead of exposing your keyset directly. A single pubnub_grant_token() call can cover any mix of resource types:

  • channels
  • groups (channel groups)
  • uuids (other users' App Context metadata)
  • categories (list all channel or uuid metadata on the subscribe key, not one named resource)

each granted either by exact resource name or by a RegEx pattern, with different permission levels per resource, all in one request. A token can be restricted to a single client through authorized_uuid and always carries a ttl after which it stops working.

Access Manager is compiled in only when the SDK is built with PUBNUB_ENABLE_PAM, which itself requires PUBNUB_ENABLE_CRYPTO:

PUBNUB_ENABLE_PAM requires PUBNUB_ENABLE_CRYPTO

Access Manager's request signing depends on the crypto provider. A build configured with PUBNUB_ENABLE_PAM=ON and PUBNUB_ENABLE_CRYPTO=OFF fails at CMake configure time with a fatal error, before any source file compiles. Enable PUBNUB_ENABLE_CRYPTO in every build that enables PUBNUB_ENABLE_PAM.

Requires Secret Key authentication

Granting permissions to resources should be done by administrators whose SDK instance has been initialized with a Secret Key (available on the Admin Portal on your app's keyset).

Secure your secret_key

Anyone who has your secret_key can grant and revoke permissions on every resource in your app. Never let secret_key be discovered, never place it in client-side code, and deliver it to your servers only over a secure channel. Once a context has a non-empty secret_key and the build enables PUBNUB_ENABLE_PAM, the SDK automatically signs every request that context sends. This includes grant, revoke, and everything else. There is no separate function to call to sign a request, and no way to opt out of signing while secret_key is set.

Grant token​

Requires Access Manager add-on

This function requires that the Access Manager add-on is enabled for your key in the Admin Portal. See Enable the features your app calls.

pubnub_grant_token() asks the server to issue a token with an embedded access-control list. Permissions are bits from pubnub_access_permission_t, OR'd together and attached to a resource name or pattern through pubnub_access_resource_permission_t.

Method(s)​

#include <pubnub/features/access.h>

pubnub_future_t pubnub_grant_token(pubnub_context_t* ctx, const pubnub_grant_token_opts_t* opts);

pubnub_access_permission_t is a uint32_t type. The permission flags are PUBNUB_ACCESS_* macros that you combine with bitwise OR:

ValueNumericMeaning
PUBNUB_ACCESS_READ1Read messages and presence events.
PUBNUB_ACCESS_WRITE2Publish messages.
PUBNUB_ACCESS_MANAGE4Add or remove channels in channel groups.
PUBNUB_ACCESS_DELETE8Delete messages from history.
PUBNUB_ACCESS_CREATE16Create resources (App Context).
PUBNUB_ACCESS_GET32Read resource metadata (App Context).
PUBNUB_ACCESS_UPDATE64Update resource metadata (App Context).
PUBNUB_ACCESS_JOIN128Join a channel (presence).

These values match the wire format directly. For example, PUBNUB_ACCESS_READ combined with PUBNUB_ACCESS_WRITE serializes as 3. Not every bit is meaningful for every resource type. See Manage Permissions with Access Manager v3 for the resource-to-permission mapping the server enforces.

Each resource entry (pubnub_access_resource_permission_t):

ParameterDescription
name
Type: const char*
Required, borrowed, NUL-terminated. An exact resource name, or a RegEx pattern string when the entry is placed in one of the pattern arrays below (for example "^chat\\..*$").
permissions
Type: uint32_t
One or more pubnub_access_permission_t values, combined with bitwise OR.

Grant options (pubnub_grant_token_opts_t):

* required
ParameterDescription
ttl *
Type: uint32_t
Minutes the token stays valid. Valid range is 1 to 43200 (30 days). 0 is rejected immediately with PUBNUB_ERR_INVALID_ARGUMENT, before any network call. There is no default.
channels
Type: const pubnub_access_resource_permission_t*
Exact channel permissions.
channel_count
Type: size_t
Entries in channels.
groups
Type: const pubnub_access_resource_permission_t*
Exact channel-group permissions.
group_count
Type: size_t
Entries in groups.
uuids
Type: const pubnub_access_resource_permission_t*
Exact uuid (App Context) permissions.
uuid_count
Type: size_t
Entries in uuids.
channel_patterns
Type: const pubnub_access_resource_permission_t*
RegEx pattern channel permissions.
channel_pattern_count
Type: size_t
Entries in channel_patterns.
group_patterns
Type: const pubnub_access_resource_permission_t*
RegEx pattern channel-group permissions.
group_pattern_count
Type: size_t
Entries in group_patterns.
uuid_patterns
Type: const pubnub_access_resource_permission_t*
RegEx pattern uuid permissions.
uuid_pattern_count
Type: size_t
Entries in uuid_patterns.
channels_category_permissions
Type: uint32_t
Category permission for all channel metadata on the subscribe key. 0 (the default) grants nothing. If non-zero, the only valid value is PUBNUB_ACCESS_GET.
uuids_category_permissions
Type: uint32_t
Category permission for all uuid metadata on the subscribe key. 0 (the default) grants nothing. If non-zero, the only valid value is PUBNUB_ACCESS_GET.
authorized_uuid
Type: const char*
Restricts the token to one client's uuid. Left NULL, the token can be used by any client that presents it.
meta
Type: const char*
A JSON metadata string embedded in the token and readable back after parsing.
timeout_ms
Type: uint32_t
Per-request timeout override. When non-zero, takes priority over the context-level transaction_timeout_ms.

PUBNUB_GRANT_TOKEN_OPTS_INIT zero-initializes every field, including ttl. Set ttl explicitly on every call, because the zero it starts at is itself an invalid value.

At least one permission is required

pubnub_grant_token() requires a permission on at least one resource, pattern, or category. A call where channels, groups, uuids, channel_patterns, group_patterns, uuid_patterns, channels_category_permissions, and uuids_category_permissions are all empty fails immediately with PUBNUB_ERR_INVALID_ARGUMENT.

C-family contract:

  • Header — #include <pubnub/features/access.h>
  • Types — pubnub_grant_token_opts_t, pubnub_access_resource_permission_t, pubnub_access_permission_t
  • Prerequisite — a context created or initialized with subscribe_key, publish_key, and secret_key set. See Identity and keys.
  • Feature flag — compiled in only when PUBNUB_ENABLE_PAM is enabled.
  • Ownership / lifetime — every string and array field on pubnub_grant_token_opts_t is borrowed. The name values inside channels, groups, uuids, and the three pattern arrays, plus authorized_uuid and meta, must all remain valid until pubnub_grant_token() returns.
  • Blocking — starts asynchronous work and returns a pubnub_future_t immediately. Validation failures such as a missing or out-of-range ttl, no permissions, or missing keys come back as an already-failed future with no network call made.

Category permissions​

A category permission covers a whole resource type instead of individual resources. Listing all channel or uuid metadata with App Context needs one, because a get on a single resource does not allow it. Set channels_category_permissions to PUBNUB_ACCESS_GET to allow listing all channel metadata, and uuids_category_permissions to PUBNUB_ACCESS_GET to allow listing all uuid metadata. Any other non-zero value makes pubnub_grant_token() return a future with PUBNUB_ERR_INVALID_ARGUMENT.

  • A category permission lets a token list all metadata of one resource type on your subscribe key. Valid categories are channels and uuids. The only permission is get (32).
  • A get permission on one named channel or user, or on a pattern, does not grant a category.
  • A token can contain only categories. It needs no resource or pattern.
  • When enumeration enforcement is enabled for a keyset, App Context list requests from a token or auth key without the matching category permission return a 403 error.

Sample code​

#include "pubnub/pubnub.h"

#include <stdio.h>

int main(void)
{
/* 1. Configure and create the client. secret_key is required for
Access Manager and must never be shipped in client-side code. */
pubnub_config_t cfg = pubnub_config_defaults();
cfg.publish_key = "demo";
cfg.subscribe_key = "demo";
cfg.secret_key = "demo";
cfg.user_id = "admin-user";

pubnub_context_t* ctx = pubnub_create(&cfg);
show all 63 lines

Returns​

pubnub_grant_token() returns a pubnub_future_t. Once pubnub_future_status() reports PUBNUB_OK, call pubnub_grant_token_result() to read the issued token:

ParameterDescription
token
Type: pubnub_string_view_t
The issued token. Valid until you call pubnub_future_release() on the future that produced it. Read or copy token.ptr/token.len before releasing.

Other examples​

Grant a token that lists all channel and uuid metadata​

The code below grants a token the get category permission for both channels and uuids, with no resources.

1

Grant using an async callback​

pubnub_grant_token() works the same way with any of the three future-consumption styles. This example uses pubnub_async() instead of cooperative polling:

#include "pubnub/pubnub.h"

#include <stdio.h>

static volatile int s_done;

static void on_grant(pubnub_future_t future, pubnub_res_t status, void* user_data)
{
(void)user_data;

if (PUBNUB_OK == status) {
pubnub_grant_token_result_t r = pubnub_grant_token_result(future);
printf("Token: %.*s\n", (int)r.token.len, r.token.ptr);
} else {
pubnub_string_view_t err = pubnub_response_error_message(future);
show all 67 lines

Error responses​

Validation failures never reach the network. They come back as an already-failed future:

ConditionResult
opts is NULLPUBNUB_ERR_INVALID_ARGUMENT
ttl is 0 or exceeds 43200PUBNUB_ERR_INVALID_ARGUMENT
no permission set on any resource, pattern, or categoryPUBNUB_ERR_INVALID_ARGUMENT
a category permission other than 0 or PUBNUB_ACCESS_GETPUBNUB_ERR_INVALID_ARGUMENT
the context or its configuration is invalidPUBNUB_ERR_INVALID_ARGUMENT
publish_key or secret_key is not set on the contextPUBNUB_ERR_INVALID_ARGUMENT
a required allocator/serialization provider is missingPUBNUB_ERR_NOT_INITIALIZED
the request queue is fullPUBNUB_ERR_QUEUE_FULL
an internal allocation failsPUBNUB_ERR_OUT_OF_MEMORY
the platform provider's wall_clock_ms callback is missing or reports 0 (no RTC / not yet NTP-synchronized), so the Access Manager request cannot be timestamp-signedPUBNUB_ERR_NO_WALL_CLOCK

A server-side rejection completes the future with PUBNUB_ERR_SERVER. Call pubnub_response_service_error() to read the normalized detail. For Access Manager responses specifically, the resulting pubnub_service_error_t.source field is populated. It is empty for every other endpoint's error shape. See Retrieving server error detail.

Revoke token​

Requires Access Manager add-on

This function requires that the Access Manager add-on, and specifically token revocation, is enabled for your key in the Admin Portal. Open your app's keyset and mark the Revoke v3 Token checkbox in the ACCESS MANAGER section.

pubnub_revoke_token() disables a token you previously issued with pubnub_grant_token(), invalidating every permission embedded in it. Use it only for tokens with a ttl of 30 days or less. For a longer-lived token, contact PubNub support.

Method(s)​

#include <pubnub/features/access.h>

pubnub_future_t pubnub_revoke_token(pubnub_context_t* ctx, const pubnub_revoke_token_opts_t* opts);

Revoke options (pubnub_revoke_token_opts_t):

* required
ParameterDescription
token *
Type: const char*
Borrowed, NUL-terminated. The token to revoke.
timeout_ms
Type: uint32_t
Per-request timeout override, same semantics as grant's timeout_ms.

PUBNUB_REVOKE_TOKEN_OPTS_INIT zero-initializes both fields. Set token explicitly before calling.

C-family contract:

  • Header — #include <pubnub/features/access.h>
  • Types — pubnub_revoke_token_opts_t
  • Prerequisite — a context configured with subscribe_key and secret_key set.
  • Feature flag — compiled in only when PUBNUB_ENABLE_PAM is enabled.
  • Ownership / lifetime — token is borrowed and must remain valid until pubnub_revoke_token() returns.
  • Blocking — starts asynchronous work and returns a pubnub_future_t immediately. A missing token or missing secret_key fails immediately with no network call made.

Sample code​

#include "pubnub/pubnub.h"

#include <stdio.h>

int main(void)
{
/* 1. Configure and create the client. */
pubnub_config_t cfg = pubnub_config_defaults();
cfg.subscribe_key = "demo";
cfg.secret_key = "demo";
cfg.user_id = "admin-user";

pubnub_context_t* ctx = pubnub_create(&cfg);
if (NULL == ctx) {
printf("pubnub_create failed\n");
show all 46 lines

Returns​

pubnub_revoke_token() returns a pubnub_future_t. There is no result struct. A successful revoke completes the future with PUBNUB_OK and nothing else to read.

Error responses​

ConditionResult
opts is NULLPUBNUB_ERR_INVALID_ARGUMENT
token is NULL or emptyPUBNUB_ERR_INVALID_ARGUMENT
the context or its configuration is invalidPUBNUB_ERR_INVALID_ARGUMENT
secret_key is not set on the contextPUBNUB_ERR_INVALID_ARGUMENT

A server-side rejection completes the future with PUBNUB_ERR_SERVER. Read the detail the same way as for Grant token. See Retrieving server error detail.

Parse token​

pubnub_parse_token() decodes a token and exposes the permissions embedded in it. Use it for debugging, or to inspect a token received from a grant response or another source before deciding whether to use it.

This call is synchronous and local, not a network request

Unlike pubnub_grant_token() and pubnub_revoke_token(), pubnub_parse_token() returns a pubnub_res_t directly, not a pubnub_future_t. It decodes the token's base64url-encoded CBOR payload locally and never contacts the server.

Method(s)​

#include <pubnub/features/access.h>

pubnub_res_t pubnub_parse_token(pubnub_context_t* ctx,
const pubnub_parse_token_opts_t* opts,
pubnub_parsed_token_t* out_result);

pubnub_parsed_token_resource_t pubnub_parsed_token_channel_at(pubnub_context_t* ctx, size_t index);
pubnub_parsed_token_resource_t pubnub_parsed_token_group_at(pubnub_context_t* ctx, size_t index);
pubnub_parsed_token_resource_t pubnub_parsed_token_uuid_at(pubnub_context_t* ctx, size_t index);
pubnub_parsed_token_resource_t pubnub_parsed_token_channel_pattern_at(pubnub_context_t* ctx, size_t index);
pubnub_parsed_token_resource_t pubnub_parsed_token_group_pattern_at(pubnub_context_t* ctx, size_t index);
pubnub_parsed_token_resource_t pubnub_parsed_token_uuid_pattern_at(pubnub_context_t* ctx, size_t index);

Parse options (pubnub_parse_token_opts_t):

* required
ParameterDescription
token *
Type: const char*
Borrowed, NUL-terminated. The base64url-encoded token string to decode.

PUBNUB_PARSE_TOKEN_OPTS_INIT zero-initializes the struct. Set token explicitly.

C-family contract:

  • Header — #include <pubnub/features/access.h>
  • Types — pubnub_parse_token_opts_t, pubnub_parsed_token_t, pubnub_parsed_token_resource_t
  • Prerequisite — none of the Access Manager keys are required. Parsing does not touch secret_key or publish_key, and it does not make a request.
  • Feature flag — compiled in only when PUBNUB_ENABLE_PAM is enabled.
  • Ownership / lifetime — the decoded resource data backing the six accessor functions lives on ctx, not on your out_result. It stays valid until the next pubnub_parse_token() call on the same context, or until pubnub_destroy()/pubnub_deinit(). The scalar fields you receive by value in out_result (version, timestamp, ttl, authorized_uuid, and the six *_count fields) are yours. Their *_count values, though, describe only that parse. Read them and call the accessors before parsing a second token on the same context.
  • Blocking — synchronous, local only. No network call, no future.
One parsed token per context

Calling pubnub_parse_token() again on the same context replaces the previously decoded data that the six indexed accessor functions read from. Your own out_result struct is unaffected, but its *_count fields become stale as loop bounds for the accessors once a second parse has happened on that context. Read everything you need, including every accessor call, from the first parse before parsing another token on the same ctx. The six accessors are not thread-safe against pubnub_parse_token() on the same context.

Sample code​

#include "pubnub/pubnub.h"

#include <stdio.h>

int main(void)
{
/* 1. Configure and create the client. No secret_key is needed to parse. */
pubnub_config_t cfg = pubnub_config_defaults();
cfg.subscribe_key = "demo";
cfg.user_id = "example-parse";

pubnub_context_t* ctx = pubnub_create(&cfg);
if (NULL == ctx) {
printf("pubnub_create failed\n");
return 1;
show all 77 lines

The code below reads the category permissions from a parsed token.

1

Returns​

pubnub_parse_token() returns PUBNUB_OK on success and populates out_result (pubnub_parsed_token_t):

ParameterDescription
version
Type: int32_t
Token format version.
timestamp
Type: uint64_t
Token creation time, Unix seconds.
ttl
Type: uint32_t
Token time-to-live, in minutes, as embedded in the token.
authorized_uuid
Type: pubnub_string_view_t
Empty (.len == 0) if the token was granted without an authorized_uuid restriction.
channel_count
Type: uint32_t
Number of exact channel permissions. This bounds pubnub_parsed_token_channel_at().
group_count
Type: uint32_t
Number of exact channel-group permissions. This bounds pubnub_parsed_token_group_at().
uuid_count
Type: uint32_t
Number of exact uuid permissions. This bounds pubnub_parsed_token_uuid_at().
channel_pattern_count
Type: uint32_t
Number of pattern channel permissions. This bounds pubnub_parsed_token_channel_pattern_at().
group_pattern_count
Type: uint32_t
Number of pattern channel-group permissions. This bounds pubnub_parsed_token_group_pattern_at().
uuid_pattern_count
Type: uint32_t
Number of pattern uuid permissions. This bounds pubnub_parsed_token_uuid_pattern_at().
channels_category_permissions
Type: uint32_t
PUBNUB_ACCESS_GET when the token carries the channels category permission, otherwise 0.
uuids_category_permissions
Type: uint32_t
PUBNUB_ACCESS_GET when the token carries the uuids category permission, otherwise 0.

Each of the six indexed accessor functions returns a pubnub_parsed_token_resource_t:

ParameterDescription
name
Type: pubnub_string_view_t
The resource name or pattern, aliasing data owned by ctx. See the ownership note above.
permissions
Type: uint32_t
The permission bits granted to this resource, as pubnub_access_permission_t values combined with bitwise OR.

On failure, out_result is zero-initialized rather than left untouched.

Error responses​

ValueMeaning
PUBNUB_OKDecoded successfully. out_result is populated.
PUBNUB_ERR_INVALID_ARGUMENTopts->token is NULL or empty.
PUBNUB_ERR_SERIALIZATIONThe token is not valid base64url, or does not decode to a valid token structure.

Set auth token​

A client that receives a token attaches it to its own context with pubnub_set_auth_token() so that every subsequent request from that context carries the token. The token can come from your server's pubnub_grant_token_result_t.token, or from any other channel you use to deliver tokens. This function is declared in client.h, not access.h. The full pubnub_config_t/runtime-setter story, including pubnub_get_auth_token(), is documented in Runtime updates. This section covers only how it applies to a token received from Access Manager.

Method(s)​

#include <pubnub/client.h>

pubnub_res_t pubnub_set_auth_token(pubnub_context_t* ctx, const char* token);
const char* pubnub_get_auth_token(const pubnub_context_t* ctx);

C-family contract:

  • Header — #include <pubnub/client.h>
  • Prerequisite — an already created or initialized context.
  • Ownership / lifetime — on a pubnub_create-based context, pubnub_set_auth_token() deep-copies token. On a pubnub_init-based context, it borrows it. pubnub_get_auth_token() returns a context-owned pointer, valid until the next pubnub_set_auth_token() call or context teardown. Do not free it.
  • Blocking — synchronous, no I/O.

This snippet is derived from the function declarations in client.h. There is no dedicated Access Manager example that exercises it.

Sample code​

#include <pubnub/client.h>

static void apply_granted_token(pubnub_context_t* ctx, const char* token)
{
pubnub_res_t res = pubnub_set_auth_token(ctx, token);
if (PUBNUB_OK != res) {
/* token was rejected -- inspect res with pubnub_res_str() */
return;
}

const char* current = pubnub_get_auth_token(ctx);
(void)current;
}

Returns​

pubnub_set_auth_token() returns PUBNUB_OK on success, PUBNUB_ERR_NOT_INITIALIZED if ctx is not initialized, or PUBNUB_ERR_OUT_OF_MEMORY if the deep-copy allocation fails (on pubnub_create-based contexts). pubnub_get_auth_token() returns the context's current auth_token, or NULL if none is set.

Was this page useful?

Last updated on