3

I opened a ticket in pubnub and also read: https://help.pubnub.com/entries/22251291-Can-I-Hide-my-Application-Keys-

But I still can't understand how can I stop the user from seeing my keys as it is still on client side even after obfuscation.

What I want to do is something I read in this post: PubNub publish message between two Private Channels

  1. Create a public channel and a private the channel for each user
  2. Hide the keys from the user

I'm not sure how to create a private channel with custom keys that the user can't see.


EDIT: I was able to understand the flow of auth_key but can't find the php equivalency for the JS crypto lib to grant permission. any idea on how to implement it in PHP?

Community
  • 1
  • 1
Danny Valariola
  • 1,118
  • 5
  • 26
  • 41
  • We are working on a PHP `$pubnub->grant()` and `$pubnub->revoke()` lib and will be ready later today or early tomorrow. – Stephen Blum Jan 14 '14 at 22:50

2 Answers2

6

You can't hide keys that are transmitted to the client and are accessible in JavaScript.

However, what you can do is restrict who can read and write to channels by using an auth_key along with your publish and subscribe keys. PubNub recently released the PubNub Access Manager to enable this. The auth_key will be specific to each user.

  1. The users auth_key will allow that user to read and write to their own private channel. You will need to set permissions so that nobody else will be able to read or write to this channel.
  2. The users auth_key will give them permission to read and write to their own public channel. Others can read, but cannot write to this channel.

Details on exactly how to do this should probably be asked in another question. The PAM getting started guide should be the best place to start.

leggetter
  • 15,248
  • 1
  • 55
  • 61
  • so, basically all users see the publish key? and who grants them the permissions? i'm a little confused regarding the flow. sry – Danny Valariola Jan 12 '14 at 14:39
  • You don't have to send the publish key to all users. Only those that may potentially publish information. You manage permissions to channels using the PAM and via a `secret_key` that you only ever use on the server and don't expose to any users. I'd recommend reading the getting started guide. – leggetter Jan 12 '14 at 16:17
  • adding to @leggetter 's link, more info on PAM is available here: http://www.pubnub.com/docs/javascript/overview/security.html – Geremy Jan 12 '14 at 18:43
  • @leggetter thanks for the help. i was able to do anything i wanted except one - i'm looking for the "grant" equivalence in PHP...any idea? – Danny Valariola Jan 12 '14 at 20:21
  • 1
    @DannyValariola I'll look for `grant` access via PHP. However you can find a Python version here: https://gist.github.com/stephenlb/8164176 – Stephen Blum Jan 14 '14 at 00:20
  • @PubNub dont bother already got a response that it's in the roadmap :( – Danny Valariola Jan 14 '14 at 13:37
  • @DannyValariola well that's totally not good enough! We need to have it today for you! PHP Grant. I'll see what I can do. – Stephen Blum Jan 14 '14 at 20:57
  • 1
    @DannyValariola hey we've started working on a port for your PHP happiness. – Stephen Blum Jan 14 '14 at 21:40
  • @PubNub, great job!! you guys mean business. – Danny Valariola Jan 15 '14 at 08:18
  • Update: We have general starting points and will be posting soon! – Stephen Blum Jan 15 '14 at 20:02
  • Update: We have some progress on the conversion though we are not passing all unit tests. We need to be sure this is ready for production level systems so we are being extra precautions on delivery. Once this is complete we will post the source code here with docs. – Stephen Blum Jan 16 '14 at 03:10
5

Hiding Your API Keys with PubNub JS SDK

Check the latest docs using PubNub Access Manager - https://www.pubnub.com/docs/security/access-control

With PubNub Access Manager you no longer need to worry about hiding your publish_key and subscribe_key in your source code in JavaScript or any other language! Typically you would consider that hiding your keys becomes a means to preventing access to streams of data on your PubNub Channels. However this is not necessary and there is a best practices method to use instead: The following is your solution for the new way to manage access and the new way to manage your keys.

PubNub Access Manager Example JS/PHP Grant Revoke SDK

You can issue per-user connection grant() and revoke() access in realtime on the PubNub global Real-Time Network. Various levels of security within the PubNub network using a grant/revoke (whitelist) permission scheme, where the first grant found in the hierarchy grants read/write access. Permissions are evaluated for both publish and subscribe based on this hierarchy. Our pam.php PubNub Access Manager PHP Class is finally ready to go! You can get started by seeing the example usage code below with full code coverage of the SDK. You can find all source code via the GitHub Gist Link:

PubNub Access Manager (PAM) PHP Full Library for Granting and Revoking Access

PubNub Access Manager (PAM) PHP Full Library for Granting and Revoking Access

Include PAM and Initialize class access

require('pam.php');

$manager = new access(
    "pub-c-e132b7b4-0c2c-4d36-a828-1de1ea50d167",
    "sub-c-f95db694-6ff9-11e3-9291-02ee2ddab7fe",
    "sec-c-OWFkNWQ1NDctN2JiNy00NzJmLTk3Y2ItN2ExODZlYzkyNzY0"
);

Grant User Access

Grant access to user with authkey of gZW5jb2RlZCBmaWx with read and write access for 5 minute ttl. You can make the authkey anything you want!

print_r($manager->grant(
    "my_channel",        // CHANNEL
    "gZW5jb2RlZCBmaWx",  // STRING (AUTH KEY)
    true,                // READ
    true,                // WRITE
    5                    // TTL in MINUTES
));

Grant User Presence Access

Also grant access to the presence channel (required for PubNub Dev Console).

print_r($manager->grant(
    "my_channel-pnpres", // CHANNEL
    "gZW5jb2RlZCBmaWx",  // STRING (AUTH KEY)
    true,                // READ
    true,                // WRITE
    5                    // TTL in MINUTES
));

Grant GLOBAL Access (to all users)

Exclude the authkey and you can global grant access to all.

print_r($manager->grant_global(
    "my_channel", // CHANNEL
    true,         // READ
    true,         // WRITE
    5             // TTL in MINUTES
));

Forever Grant Access

You can grant access forever by setting the ttl param to 0.

print_r($manager->grant_global(
    "my_channel", // CHANNEL
    true,         // READ
    true,         // WRITE
    0             // FOREVER GRANT!!!
));

Revoke User Access

Instantly revoke access to a user.

print_r($manager->revoke(
    "some-other-channel", // CHANNEL
    "gZW5jb2RlZCBmaWx"    // STRING (AUTH KEY)
));

Revoke Global Access

You can also revoke Global Access by excluding the authkey param.

print_r($manager->revoke(
    "some-other-channel" // CHANNEL
));

PAM (PubNub Access Manager) PHP Class SDK pam.php

The full file can be found here: PubNub Access Manager (PAM) PHP Full Library for Granting and Revoking Access

<?php

class access {
    function __construct( $pubkey, $subkey, $seckey ) {
        $this->publish_key   = $pubkey;
        $this->subscribe_key = $subkey;
        $this->secret_key    = $seckey;
    }

    function grant_global( $channel, $read=True, $write=True, $ttl=5 ) {
        /**  Grant GLOBAL Access on a Channel. **/
        return $this->_auth(array(
            "channel" => $channel,
            "r"       => $read  ? 1 : 0,
            "w"       => $write ? 1 : 0,
            "ttl"     => $ttl
        ));
    }

    function grant( $channel, $authkey=False, $read=True, $write=True, $ttl=5 ) {
        /**  Grant Access on a Channel. **/
        return $this->_auth(array(
            "channel" => $channel,
            "auth"    => $authkey,
            "r"       => $read  ? 1 : 0,
            "w"       => $write ? 1 : 0,
            "ttl"     => $ttl
        ));
    }

    function revoke( $channel, $authkey=False, $read=False, $write=False, $ttl=1 ) {
        /**  Revoke Access on a Channel.**/
        return $this->_auth(array(
            "channel" => $channel,
            "auth"    => $authkey,
            "r"       => $read  ? 1 : 0,
            "w"       => $write ? 1 : 0,
            "ttl"     => $ttl
        ));
    }

    function _sign($message) {
        /** Calculate a signature by secret key and message. **/
        return strtr( base64_encode(hash_hmac(
            'sha256',
            utf8_encode($message),
            utf8_encode($this->secret_key),
            true
        )), '+/', '-_' );
    }

    function _auth($query) { 
        /** Issue an authenticated request.**/
        if (!array_key_exists( 'timestamp', $query )) {
            $query['timestamp'] = time();
        }

        ## Global Grant?
        if ((array_key_exists('auth',$query)) && !$query['auth']) { 
            unset($query['auth']);
        }

        ## Construct String to Sign
        $params      = array();
        $sorted_keys = array_keys($query);
        sort($sorted_keys);

        foreach ($sorted_keys as $key) array_push(
            $params,
            $key . "=" . $query[$key]
        );

        $string_to_sign = 
            $this->subscribe_key . "\n" .
            $this->publish_key   . "\n" .
            "grant"              . "\n" .
            implode( "&", $params );

        $signature = $this->_sign($string_to_sign);
        $url       = (
            "https://pubsub.pubnub.com/v1/auth/grant/sub-key/" .
            $this->subscribe_key . "?" .
            implode( "&", $params ) .
            "&signature=" . $signature
        );

        $workspace_curl = curl_init();  
        curl_setopt( $workspace_curl, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt( $workspace_curl, CURLOPT_URL, $url );
        $result = curl_exec($workspace_curl);
        return $workspace_details =json_decode( $result, true );
    }
}

?>

pam.php: PubNub Access Manager (PAM) PHP Full Library for Granting and Revoking Access

PubNub Dev Console Test Link:

WARNING: PubNub Dev Console Requires Grant on Presence Channel too! You can set the presence access by granting on the suffix of -pnpres channel name.

http://www.pubnub.com/console/?channel=my_channel&sub=sub-c-f95db694-6ff9-11e3-9291-02ee2ddab7fe&pub=pub-c-e132b7b4-0c2c-4d36-a828-1de1ea50d167&sec=sec-c-OWFkNWQ1NDctN2JiNy00NzJmLTk3Y2ItN2ExODZlYzkyNzY0

Stephen Blum
  • 6,498
  • 2
  • 34
  • 46
  • 1
    This answers a different question to the one that was asked. I'd recommend that new question be raised asking how you can grant and revoke access to channels via PHP. This is then the perfect answer to that question. This doesn't answer "how to hide pubnub keys when using JS". – leggetter Jan 18 '14 at 09:07
  • @DannyValariola I'm guessing you've revoked the acceptance of my answer and have accepted this one. However, as my comment above, the original question asked "how to hide pubnub keys when using JS". This answer is an excellent answer to managing access to channels, but doesn't answer the question on this page. If the PHP question is raised as another question then this is a perfect answer. The point here is that we need to make sure that the answers match the questions so that other users get the most benefit out of them. – leggetter Jan 19 '14 at 17:19
  • @leggetter good point you make! Check this out: since the launch of **PubNub Access Manager** the question of *"How to Hide Keys"* now has a new meaning. We are in an awesome bright new future! This fantastic future includes new power features and capabilities that didn't exist before now. You no longer need to hide your API Keys; the best practices have changed for the better. *When customers ask "How to Hide Keys"* the answer is: **"You don't have too! Use PAM instead."** – Stephen Blum Jan 19 '14 at 20:19
  • @PubNub- Question: "how to hide pubnub keys when using JS" -> Answer: "PubNub Access Manager PHP Grant and Revoke SDK". These don't match up. The statement "With PubNub Access Manager you no longer need to worry about hiding your publish_key and subscribe_key in your source code!" doesn't *directly* answer either. I'd suggest updating the opening para to clarify *you can't hide the keys in JS on the client*. There's an edit to the Q that says "any idea on how to implement it in PHP?". IMHO is a new Q to which a new A should've been written. See http://meta.stackoverflow.com/help/how-to-answer – leggetter Jan 19 '14 at 20:51
  • @leggetter I am super happy that you asked! You have a good point. :-) Check this out: #1 **Yes you can** indeed hide your API keys in JavaScript. #2 You don't have to hide your keys. Following the tunnel of logical follow-on questions, the answer becomes ultimately PAM w/ PHP. Check this out: Q: "How to Hide Keys?", A: "You can, but you should use PAM instead". Which follows: Q: "How to use PAM with PHP and JavaScript?" A: "Here is the SDK source." JavaScript: http://www.pubnub.com/docs/javascript/tutorial/access-manager.html and PHP https://gist.github.com/stephenlb/8483690 – Stephen Blum Jan 19 '14 at 21:04
  • @PubNub well, if the "A" is "You can, but you should use PAM instead", then more descriptive answer which explains "HOW to hide them in JS?" should be accepted, not this one. – peetonn Dec 23 '16 at 00:40
  • You can't hide anything in JavaScript. Access Manager provide the most secure way to prevent trusted/registered uses from abusing your keys (subscribing/publishing on channels they are not allowed to) and malicious hackers. TLS and encryption in conjunction with Access Manager is the ultimate security. See Leggetter's answer below. I think he already answered this. – Craig Conover Dec 24 '16 at 05:54
  • Check the latest docs using PubNub Access Manager - https://www.pubnub.com/docs/security/access-control – Stephen Blum May 26 '21 at 17:30