Access Manager v3 Migration Guide
Access Manager v3 is a new cryptographic, token-based permission administrator that allows you to regulate clients' access to PubNub resources, such as channels, channel groups, and User IDs. Access Manager provides developers with tools to increase the security of their applications and block end users from accessing resources that they haven't been explicitly granted permission for. This document is aimed at developers who already use previous versions of Access Manager in their existing applications.
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.
While the way that customer applications interact with Access Manager hasn't changed fundamentally from v2 to v3, the new version significantly lowers latency and provides higher operational stability. In general, we've moved the complexity of the Access Manager logic from the authorization request to the grant request. The new flow guarantees that tokens returned by the grant API will work immediately. It also reduces the likelihood that end users will experience latency when their clients are making PubNub API requests. Finally, the new system provides an increased set of security options and improves flexibility in terms of setting and verifying permissions. For more details, see the Access Manager v3 feature description.
If your application uses Access Manager v2 to manage access to resources, we'll continue to process your requests. However, we strongly recommend that you migrate to the new Access Manager v3 service. This guide provides an overview of all differences between the two versions, compares their data flows, and documents the steps you need to follow to migrate to Access Manager v3.
Differences between v2 and v3
See all the major differences between the two versions:
Feature | Access Manager v2 | Access Manager v3 |
---|---|---|
Authentication method | Authentication key generated by the client. | Token generated by PubNub upon a grant request made by the server. |
Permissions storage | Permissions are stored as an access control list (ACL) in the database on the PubNub server. | Permissions are embedded in a token (self-contained). |
Permissions expiration | Each resource has its own unique ttl (time to live). | There is one ttl that's set at a token level. |
Authorization check latency | Database lookup is required and that increases latency. | Instant check as permissions are embedded in the token. |
Grant latency | High latency | Low latency - clients can connect immediately after they receive tokens. |
Pattern-based permissions | It supports only one-level wildcard notations (a.* ) for the channel resource. | It supports RegEx for channels , groups (channel groups), and uuids . |
Multiple permission grants | You must make separate API calls for multiple permission sets. | You can make a single API call to define multiple permission sets for a given authorized User ID. |
Differences in data flows
Typical PubNub solutions that use Access Manager include a centralized, customer-developed server application that initializes a PubNub SDK with a secretKey
allowing the server to make calls to the PubNub grant API. Clients connect with this server through application-specific interfaces developed by the customer. The following descriptions show examples of client-server interactions initiated by a user logging in to the client device. The idea behind it is to demonstrate how permissions are governed and distributed in both Access Manager versions, and how these flows differ.
Access Manager v2
A client will typically log in to a server application that first identifies the set of permissions associated with that client's user and later creates an authKey
for it. The authKey
and a defined permission set are sent to PubNub by the server in a grant call. PubNub stores the permissions mapping for the provided authKey
in a database. Your client device passes this authKey
during PubNub object initialization and retains it across multiple API calls. When the authKey
expires and the client device attempts to log in again, it will have to request to be re-granted further access.
Access Manager v3
A client connects to the server application to initialize itself. That typically happens during a login attempt. Depending on your application logic, the client may present the permissions it needs, and your server will have a way of authenticating that this request is coming from an approved client. Alternatively, your client will be providing some type of identity request and your server will determine the appropriate permissions for that user. In either case, the server makes a grant request to PubNub to get a token with these permissions. In this grant request, the server defines how long these permissions should be valid. In turn, PubNub generates a time-limited, signed token with embedded permissions and returns the token to the server. The server passes this token back to the client device so it can communicate directly with PubNub. When the client device wants to change the permissions, the token is about to expire, or has been revoked, the client calls the server to request PubNub to grant a new token. Once the server receives a new one, it passes the token back to the client device.
Token size limits
There's a 32 KiB limit for the overall size of an HTTP request including a token. To avoid errors due to excessively large tokens in requests, set permissions with RegEx and use consistent naming conventions for your resources. See the channel naming convention for reference, or contact support for any questions.
Migration steps
To migrate from Access Manager v2 to v3:
- Remove
authKey
from your client-side configuration and prepare the logic to set the token (which is returned by your server):
- Node.js
- Python
- Java
- Kotlin
- Go
- C#
- Dart
- PHP
- Ruby
const pubnub = new PubNub({
subscribeKey: "mySubscribeKey",
publishKey: "myPublishKey",
userId: "myUniqueUserId"
});
pubnub.setToken("yourToken"); // Set the token returned by the server (see the next step for more details)
pn_config = PNConfiguration()
pn_config.subscribe_key = "my_subscribe_key"
pn_config.publish_key = "my_publish_key"
pn_config.user_id = "my_unique_user_id"
pubnub = PubNub(pn_config)
pubnub.set_token("your_token") # Set the token returned by the server (see the next step for more details)
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "yourSubscribeKey");
configBuilder.publishKey("myPublishKey");
PubNub pubNub = PubNub.create(configBuilder.build());
pubNub.setToken("yourToken");
// Set the token returned by the server (see the next step for more details)
val pnConfiguration = PNConfiguration(UserId("myUserId")).apply {
subscribeKey = "my_subkey"
publishKey = "my_pubkey"
secure = true
}
val pubnub = PubNub.create(pnConfiguration)
pubnub.setToken("yourToken"); // Set the token returned by the server (see the next step for more details)
pnconfig := pubnub.NewConfig()
pnconfig.SubscribeKey = "MySubscribeKey"
pnconfig.PublishKey = "MyPublishKey"
pnconfig.SetUserId(UserId("myUniqueUserId"))
pn := pubnub.NewPubNub(pnconfig)
pn.SetToken("NewToken") // Set the token returned by the server (see the next step for more details)
PNConfiguration pnconfig = new PNConfiguration();
pnconfig.SubscribeKey = "mySubscribeKey";
pnconfig.PublishKey = "myPublishKey";
pnconfig.UserId = "MyUniqueUserId";
Pubnub pubnub = new Pubnub(pnconfig);
pubnub.SetAuthToken("NewToken") // Set the token returned by the server (see the next step for more details)
final myKeyset = Keyset(
subscribeKey: 'mySubscribeKey',
publishKey: 'myPublishKey',
userId: UserId('yourUniqueUserId')
);
pubnub.setToken("yourToken") // The token is returned by the server in the next step
use PubNub\PNConfiguration;
$pnConfiguration = new PNConfiguration();
$pnConfiguration->setSubscribeKey("MySubscribeKey");
$pnConfiguration->setPublishKey("MyPublishKey");
$pnConfiguration->setUuid("MyUniqueUuid");
$pubnub->setToken("NewToken");
pubnub = Pubnub.new(
subscribe_key: 'my_subscribe_key',
publish_key: 'my_publish_key',
user_id: 'myUniqueUserId'
);
pubnub.set_token("newToken"); # Set the token returned by the server (see the next step for more details)
Tokens may need to be updated for various reasons. One reason could be because the user’s permissions have changed. Applications that securely authenticate client connections may allow clients to request changes to their own permissions. Other architectures may initiate changes on the server side and notify clients that they need a new token. Regardless of the approach, server logic should provide an interface that clients can call to request a new token.
Clients may also need to request a new token if it has (or will soon be) expired. Clients that make PubNub API requests with an expired token will get a 403
response.
Regardless of why a client has requested a new token, the server logic should make a new grant request and return the new token to the client. Once clients have the new token, they can set it in their PubNub object the same way they set a brand new token. Make sure not to create a new PubNub object on every token update, but rather set the token using the set_token()
method (name may vary) available in your SDK.
For more information, refer to Manage Permissions with Access Manager.
- Update your server-side code around grant APIs:
- Node.js
- Python
- Java
- Kotlin
- Go
- C#
- Dart
- PHP
- Ruby
const pubnub = new PubNub({
subscribeKey: "mySubscribeKey",
publishKey: "myPublishKey",
secretKey: "mySecretKey",
userId: "myUniqueUserId"
});
pubnub.grantToken(
{
ttl: 15,
authorized_uuid: "myAuthorizedUUID",
resources: {
channels: {
"myChannel": {
read: true // False to disallow
show all 23 linespn_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)
envelope = pubnub.grant_token()
.channels([Channel.id(channel).read() for channel in ("my_channel")])
.ttl(15)
.authorized_uuid("my_authorized_uuid")
.sync()
# Provide logic to return this token to your client
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());
pubNub.grantToken()
.ttl(15)
.authorizedUUID("myAuthorizedUUID")
.channels(Arrays.asList(ChannelGrant.name("myChannel").read()
.async(result -> { /* check result */ });
val pnConfiguration = PNConfiguration(UserId("myUserId")).apply {
subscribeKey = "my_subkey"
publishKey = "my_pubkey"
secretKey = "my_secretkey"
secure = true
}
val pubnub = PubNub.create(pnConfiguration)
pubnub.grantToken(
ttl = 15,
authorizedUUID = "my-authorized-uuid",
channels = listOf(ChannelGrant.name(name = "my-channel", read = true))
).async { result ->
result.onFailure {
// Handle error
}.onSuccess {
show all 19 linespnconfig := pubnub.NewConfig()
pnconfig.SubscribeKey = "MySubscribeKey"
pnconfig.PublishKey = "MyPublishKey"
pnconfig.SecretKey = "MySecretKey"
pnconfig.SetUserId(UserId("myUniqueUserId"))
pn := pubnub.NewPubNub(pnconfig)
pn := pubnub.NewPubNub(pnconfig)
res, status, err := pn.GrantToken().
TTL(15).
AuthorizedUUID("my-authorized-uuid").
Channels(map[string]pubnub.ChannelPermissions{
"my_channel": {
Read: true,
},
show all 19 linesPNConfiguration pnconfig = new PNConfiguration();
pnconfig.SubscribeKey = "mySubscribeKey";
pnconfig.PublishKey = "myPublishKey";
pnconfig.SecretKey = "mySecretKey";
pnconfig.UserId = "MyUniqueUserId";
Pubnub pubnub = new Pubnub(pnconfig);
PNResult<PNAccessManagerTokenResult> grantTokenResponse = await pubnub.GrantToken()
.TTL(15)
.AuthorizedUuid("my-authorized-uuid")
.Resources(new PNTokenResources()
{
Channels = new Dictionary<string, PNTokenAuthValues>() {
{ "my-channel", new PNTokenAuthValues() { Read = true } } } // False to disallow
})
show all 29 linesfinal myKeyset = Keyset(
subscribeKey: 'mySubscribeKey',
publishKey: 'myPublishKey',
secretKey: 'mySecretKey',
userId: UserId('yourUniqueUserId')
);
// Prepare the request object
var request = pubnub.requestToken(ttl: 15, authorizedUUID: 'my-authorized-uuid');
request.add(ResourceType.channel, name: 'my-channel', read: true);
// Send the token request
var token = await pubnub.grantToken(request);
print('grant token = $token');
show all 16 linesuse PubNub\PNConfiguration;
$pnConfiguration = new PNConfiguration();
$pnConfiguration->setSubscribeKey("MySubscribeKey");
$pnConfiguration->setPublishKey("MyPublishKey");
$pnConfiguration->setSecretKey("MySecretKey");
$pnConfiguration->setUserId("MyUniqueUserId");
$token = $pubnub->grantToken()
->ttl(15)
->authorizedUuid('my-authorized-uuid')
->addChannelResources([
'my-channel' => ['read' => true, 'write' => true, 'update' => true],
])
->sync();
);
show all 17 linespubnub = Pubnub.new(
subscribe_key: 'my_subscribe_key',
publish_key: 'my_publish_key',
secret_key: 'my_secret_key',
user_id: 'myUniqueUserId'
);
pubnub.grant_token(
ttl: 15,
authorized_uuid: "my-authorized-uuid",
channels: {
"my-channel": Pubnub::Permissions.res(
read: true
)
}
show all 18 linesBilling and pricing
Transactions in Access Manager v3 are counted in the same way as in v2, but you need to consider these changes and their effects:
-
In Access Manager v2, a developer has to make separate grant calls for the same client device. This means that you have to make separate grant calls if you want to grant different permissions for multiple resources (
read
tochannel1
andwrite
tochannel2
). In Access Manager v3, you can create multiple resource-permission mappings in a single call. This change can lower your monthly bill as you may observe some reduction in the overall number of transactions. -
In Access Manager v3, it's recommended that you set your token with
ttl
between10
to60
minutes. If yourttl
in v2 was set for a longer period of time, migrating to Access Manager v3 would incur more grant calls and may impact your monthly bill. -
In Access Manager v2, the
authKey
is a permissions identifier. These identifiable permissions are stored and replicated in PubNub's databases. In Access Manager v3, revoked tokens are stored on a denylist in the PubNub database. Typically, the storage space used by the v2 permissions is much bigger compared to the storage space used by the v3's denylist. However, database entries of both the v2 and v3 impact your storage capacity and are charged towards your monthly bill.
Access Manager v2
If you want to learn more about the previous version (v2) of Access Manager, refer to this feature description.