Access Manager v3 API for C SDK
Access Manager v3 (PAM) 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:
channelsgroups(channel groups)uuids(other users' App Context metadata)
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. Read the support page on enabling add-on features on your keys.
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);
Permission bits (pubnub_access_permission_t), combined with bitwise OR into a uint32_t:
| Value | Numeric | Meaning |
|---|---|---|
PUBNUB_ACCESS_READ | 1 | Read messages and presence events. |
PUBNUB_ACCESS_WRITE | 2 | Publish messages. |
PUBNUB_ACCESS_MANAGE | 4 | Add or remove channels in channel groups. |
PUBNUB_ACCESS_DELETE | 8 | Delete messages from history. |
PUBNUB_ACCESS_CREATE | 16 | Create resources (App Context). |
PUBNUB_ACCESS_GET | 32 | Read resource metadata (App Context). |
PUBNUB_ACCESS_UPDATE | 64 | Update resource metadata (App Context). |
PUBNUB_ACCESS_JOIN | 128 | Join 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):
| Parameter | Description |
|---|---|
nameType: 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\\..*$"). |
permissionsType: uint32_t | One or more pubnub_access_permission_t values, combined with bitwise OR. |
Grant options (pubnub_grant_token_opts_t):
| Parameter | Description |
|---|---|
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. |
channelsType: const pubnub_access_resource_permission_t* | Exact channel permissions. |
channel_countType: size_t | Entries in channels. |
groupsType: const pubnub_access_resource_permission_t* | Exact channel-group permissions. |
group_countType: size_t | Entries in groups. |
uuidsType: const pubnub_access_resource_permission_t* | Exact uuid (App Context) permissions. |
uuid_countType: size_t | Entries in uuids. |
channel_patternsType: const pubnub_access_resource_permission_t* | RegEx pattern channel permissions. |
channel_pattern_countType: size_t | Entries in channel_patterns. |
group_patternsType: const pubnub_access_resource_permission_t* | RegEx pattern channel-group permissions. |
group_pattern_countType: size_t | Entries in group_patterns. |
uuid_patternsType: const pubnub_access_resource_permission_t* | RegEx pattern uuid permissions. |
uuid_pattern_countType: size_t | Entries in uuid_patterns. |
authorized_uuidType: const char* | Restricts the token to one client's uuid. Left NULL, the token can be used by any client that presents it. |
metaType: const char* | A JSON metadata string embedded in the token and readable back after parsing. |
timeout_msType: 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 or pattern. A call where channels, groups, uuids, channel_patterns, group_patterns, and uuid_patterns 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, andsecret_keyset. See Identity and keys. - Feature flag — compiled in only when
PUBNUB_ENABLE_PAMis enabled. - Ownership / lifetime — every string and array field on
pubnub_grant_token_opts_tis borrowed. Thenamevalues insidechannels,groups,uuids, and the three pattern arrays, plusauthorized_uuidandmeta, must all remain valid untilpubnub_grant_token()returns. - Blocking — starts asynchronous work and returns a
pubnub_future_timmediately. Validation failures such as a missing or out-of-rangettl, no permissions, or missing keys come back as an already-failed future with no network call made.
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 linesReturns
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:
| Parameter | Description |
|---|---|
tokenType: 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 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 linesError responses
Validation failures never reach the network. They come back as an already-failed future:
| Condition | Result |
|---|---|
opts is NULL | PUBNUB_ERR_INVALID_ARGUMENT |
ttl is 0 or exceeds 43200 | PUBNUB_ERR_INVALID_ARGUMENT |
| no permission set on any resource or pattern | PUBNUB_ERR_INVALID_ARGUMENT |
| the context or its configuration is invalid | PUBNUB_ERR_INVALID_ARGUMENT |
publish_key or secret_key is not set on the context | PUBNUB_ERR_INVALID_ARGUMENT |
| a required allocator/serialization provider is missing | PUBNUB_ERR_NOT_INITIALIZED |
| the request queue is full | PUBNUB_ERR_QUEUE_FULL |
| an internal allocation fails | PUBNUB_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 PAM request cannot be timestamp-signed | PUBNUB_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):
| Parameter | Description |
|---|---|
token *Type: const char* | Borrowed, NUL-terminated. The token to revoke. |
timeout_msType: 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_keyandsecret_keyset. - Feature flag — compiled in only when
PUBNUB_ENABLE_PAMis enabled. - Ownership / lifetime —
tokenis borrowed and must remain valid untilpubnub_revoke_token()returns. - Blocking — starts asynchronous work and returns a
pubnub_future_timmediately. A missingtokenor missingsecret_keyfails 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 linesReturns
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
| Condition | Result |
|---|---|
opts is NULL | PUBNUB_ERR_INVALID_ARGUMENT |
token is NULL or empty | PUBNUB_ERR_INVALID_ARGUMENT |
| the context or its configuration is invalid | PUBNUB_ERR_INVALID_ARGUMENT |
secret_key is not set on the context | PUBNUB_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):
| Parameter | Description |
|---|---|
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_keyorpublish_key, and it does not make a request. - Feature flag — compiled in only when
PUBNUB_ENABLE_PAMis enabled. - Ownership / lifetime — the decoded resource data backing the six accessor functions lives on
ctx, not on yourout_result. It stays valid until the nextpubnub_parse_token()call on the same context, or untilpubnub_destroy()/pubnub_deinit(). The scalar fields you receive by value inout_result(version,timestamp,ttl,authorized_uuid, and the six*_countfields) are yours. Their*_countvalues, 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.
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 linesReturns
pubnub_parse_token() returns PUBNUB_OK on success and populates out_result (pubnub_parsed_token_t):
| Parameter | Description |
|---|---|
versionType: int32_t | Token format version. |
timestampType: uint64_t | Token creation time, Unix seconds. |
ttlType: uint32_t | Token time-to-live, in minutes, as embedded in the token. |
authorized_uuidType: pubnub_string_view_t | Empty (.len == 0) if the token was granted without an authorized_uuid restriction. |
channel_countType: uint32_t | Number of exact channel permissions. This bounds pubnub_parsed_token_channel_at(). |
group_countType: uint32_t | Number of exact channel-group permissions. This bounds pubnub_parsed_token_group_at(). |
uuid_countType: uint32_t | Number of exact uuid permissions. This bounds pubnub_parsed_token_uuid_at(). |
channel_pattern_countType: uint32_t | Number of pattern channel permissions. This bounds pubnub_parsed_token_channel_pattern_at(). |
group_pattern_countType: uint32_t | Number of pattern channel-group permissions. This bounds pubnub_parsed_token_group_pattern_at(). |
uuid_pattern_countType: uint32_t | Number of pattern uuid permissions. This bounds pubnub_parsed_token_uuid_pattern_at(). |
Each of the six indexed accessor functions returns a pubnub_parsed_token_resource_t:
| Parameter | Description |
|---|---|
nameType: pubnub_string_view_t | The resource name or pattern, aliasing data owned by ctx. See the ownership note above. |
permissionsType: 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
| Value | Meaning |
|---|---|
PUBNUB_OK | Decoded successfully. out_result is populated. |
PUBNUB_ERR_INVALID_ARGUMENT | opts->token is NULL or empty. |
PUBNUB_ERR_SERIALIZATION | The 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-copiestoken. On apubnub_init-based context, it borrows it.pubnub_get_auth_token()returns a context-owned pointer, valid until the nextpubnub_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.