PubNub Access Manager Tutorial

Fine grain access control to streams of data by person, device or channel
PubNub Access Manager Tutorial

PubNub Access Manager Tutorial

Access Manager extends PubNub's existing security framework by allowing developers to create and enforce secure access to channels throughout the PubNub Data Stream Network.

Access Manager enables the following functions:

  • Syndicating streams by authorizing users to read/write messages on one or more channels
  • Granting/revoking permissions for your realtime streams at the user/device, channel, or key level
  • Working with Auth tokens from any existing authentication system: OAuth (Facebook Connect, Twitter, Google, GitHub, etc.), LDAP, or homegrown solutions

Access Manager is critical for social apps and chat rooms where secure real-time communication is peer-to-peer, with the option to monitor and intervene in user interactions when needed (e.g. ban a user, change privileges on a private chat room, etc.).

IoT / Home Automation Device management, where secure real-time data is streaming bi-directionally between registered devices, allows users to get device status and control devices such as light bulbs, door locks, temperature sensors, and security cameras.

Subscription services allow companies to offer subscription-based streams (e.g. financial services, trading signals, data feeds, consumer subscriptions) and enforce user limits and data access by granting and/or revoking privileges to the data streams based on what access the user has purchased.

Multiplayer gaming for real-time interaction, where players are granted access to restricted area, stages, etc.

And many more - nearly every use case that needs PubNub's Data Stream Network could also benefit from using Access Manager.

To get started, check out the live demo that shows Access Manager in action and download the source code from GitHub:

Live Demo:

Source Code:

This simple light-weight demo is written in JavaScript for both the client (Web Browser) and server (Node.js). This example is good for a small-scale chat app, and merely one way to authorize users' read/write access to familiarize you with Access Manager APIs.

Let's get started.

 

  1. Authenticate User: When a user accesses the web app (client) for the first time, the user is asked to sign in using a GitHub credential.
  2. Use authKeys to Grant Access: Once the user logs in, the user is given an auth token from OAuth. The token is used as an authKeys that the admin (server) can reference to grant read/write permission to the user.
  3. Send Messages: the client sends the message with a digital signature. Digital signatures are fingerprints with embedded secure cryptographic hashes of key components of the message payload, and used to block spoofers.
  4. Receive Messages: Simultaneously, web clients of all users on the chat channel subscribe the message from PubNub stream. Messages are displayed only when the messages are verified authentic.

Subscribe Message

Access Manager allows you to manage granular permissions for your real-time apps and data streams, create multiple permission levels, grant and revoke access. This guide walks through how to use Access Manager by providing code samples from the demo app outlined above.

To use Access Manager, you need to enable Access Manager in the Admin Dashboard. Caution: Once you enable Access Manager, you must grant permissions before any data can be sent or received.

Enable Access Manager Add-on

 

Access Manager Add-on Configuration

 

Access Manager APIs are included in pubnub.js, so you can include either pubnub.js or pubnub.min.js, with a specific version, in your HTML file as usual:

<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.[version number].js"></script>[1] 

Be sure to include the latest version, which is available in the JavaScript documentation.

If you are using PubNub JavaScript SDK version 3.6 or older, in addition to the pubnub.js file (pubnub-[version].min.js), you also need to include:

<script src="https://cdn.pubnub.com/pubnub-crypto.min.js"></script>[2]

Initialization

When using Access Manager, use admin mode for administrative users who have access to grant/deny a user permission, and general user mode for the rest of the users.

Admin Mode

To initialize your instance with an administrative function, you need to include your secretKey, which you should be able to find in the Admin portal along with your subscribe and publish keys:

Your Keys

All the admin actions (setting secretKey, grant, revoke, etc.) should be done on the server side, since you don't want to expose the secretKey on the client side.

The example below is in node.js:

var pubnub = require('pubnub').PubNub({
    subscribeKey: 'sub-c-f762fb78-...',
    publishKey: 'pub-c-156a6d5f-...',
    secretKey: 'sec-c-M2U0N...'
});

User Mode

Initialize your client with authKey to identify each subscriber.

var pubnub = new PubNub({
    subscribeKey: 'sub-c-f762fb78-...',
    publishKey: 'pub-c-156a6d5f-...',
    authKey: 'my_auth_key_from_login'
});

The arbitrary authKey should be unique. It can be a uuid, or an authentication token from OAuth (Facebook Connect, Twitter, Google, GitHub, etc.), LDAP, RADIUS, or any other authentication system. The admin uses the authKey to control and monitor users.

In the demo, we use an OAuth token from a GitHub login as an authKey.

If at any point during runtime you need to reset the auth key, you can call the setAuthKey() method to set it again:

Only an admin can grant access to a user. This operation should only be done on the server side.

With Access Manager, you can grant access:

  • on a global level
  • on a channel/channel group level
  • on a channel/channel group + auth key level

For example, when you are creating a chat app, you can manage chat rooms (= channels) or users (= auth keys).  If you are creating a home automation system, you might grant write access to the light bulbs to send their status data and read access so a user can control them remotely via a smartphone app. In other words, you would grant read access to users who will receive data, and write access to users who have permission to control the light’s operations.

Granting all users access to all channels

This example grants read and write privileges to all users for 60 minutes (functionally equivalent to disabling PubNub Access Manager for a short time):

pubnub.grant(
    {
        ttl: 60,
        read: true,
        write: true
    },
    function (status) {
        // handle state setting response
    }
);

The default ttl (time-to-live) value is 24 hours (1440 minutes). When you set ttl as 0, it grants access forever and never expires.

Admin calls should always include an error handler. These functions are especially sensitive to some conditions such as clock drift. Be sure to install and properly configure your servers to prevent this specific error case.

Granting all users access to a single channel

When you specify a channel name (or group), you can grant all users access to the specific channel (or group) only. This example uses the default ttl:

pubnub.grant(
    {
        channels: ["public-room"],
        read: true,
        write: true
    },
    function (status) {
        // handle state setting response
    }
);

Granting a user access to a private channel

This example grants 60 minute read and write privileges on a channel to a user, who is associated with a particular authKeys:

pubnub.grant(
    {
        channels: ["private-83659357"],
        authKeys: ["abcxyz123-auth-key"],
        ttl: 60,
        read: true,
        write: true
    },
    function (status) {
        // handle state setting response
    }
);

If the authKeys param is not included, a global grant is issued to all users who are subscribed to the channel.

Example

In this chat room example, the admin only grants users, who has signed in with GitHub login, using the OAuth token as an authKeys.

var channel = "auth-chat";

pubnub.grant(
    {
        channels: [channel],
        authKeys: ["9ae4c23e1a8c6654efddf98c2b8ab5fba3f"], // OAuth token
        read: true,
        write: true
    },
    function (status) {
        // handle state setting response
    }
);

When a user types a message in a form field and clicks a "Send" button on the browser, the message is published with a digital signature.

Access Manager 4

Publishing a simple message in the client looks like this:

send.addEventListener('click', function(e) {
    pubnub.publish({
        message: { 
            text: input.value
        },
        channel : channel
    });
}, false);
 
Note: In the real-life scenario for an application in production, you should use a public key infrastructure (PKI) to create digital certificates and manage public-key encryption to eliminate spoofing, however, we are not discussing the subject in this tutorial. To learn more about security, please refer Chat Security: User Identification with Digital Signature Message Verification article, and take a look at the source code on GitHub to see how the demo chat app uses Elliptic curve cryptography (ECC).

If a user (let's say the user has an authKeys, xyz789) has never granted the write access, and tries to publish in the manner, the user get a 403 error with this log:

["PUBLISH ERROR",{"message":"Forbidden","payload":{"channels":["my-chat"]}}]

Only an admin can revoke access from a user. The easiest way to deny read and write access grant() method with read and write set to false. This operation should be done on the server side.

pubnub.grant({
    read: false,
    write: false,
    ...
});

When you are revoking access from a particular user for a particular channel, use the user's authKeys.

pubnub.grant({ 
    channels : [channel],
    authKeys : ["9ae4c23e1a8c6654efddf98c2b8ab5fba3f..."]
});

If the authKeys param is not included, access is revoked on that channel globally for all users.

When you are using PubNub Presence in your app (e.g. displaying how many users are online), you need to grant users access to particular presence channels in order to read the corresponding presence data.

You can allow read access to the presence channel name which is specified by adding the -pnpres suffix to the original channel name. For example, when the channel name is "my-chat", the presence channel name is "my-chat-pnpres".

pubnub.grant(
    {
        channels: [channel+'-pnpres'],
        authKeys: ['user-auth'],
        read: true,
        write: false
    },
    function (status) {
        // handle state setting response
    }
);
Tags: 
Access Manager

Try PubNub Today

Connect up to 100 devices for Free