JSON Web Token authentication

Both Socket connections and REST API can be authenticated using JSON Web Tokens (JWT). The token is encoded using your channel's secret. There are JWT libraries for most programming languages and it is relatively easy to implement yourself.

JWT Header

JWT has to be encoded with HMAC using SHA-256 (HS256). The decoded header always looks like this:

{"alg": "HS256", "typ": "JWT"}

JWT Payload

JWT's payload uses the common ext JWT claim and some Scaledrone's specific claims. An example decoded JWT payload looks like this:

{
  "client": "client_id_sent_from_javascript_client",
  "channel": "channel_id",
  "permissions": {
    ".*": {
      "publish": true,
      "subscribe": true
    },
    "^main-room$": {
      "publish": false,
      "subscribe": false
    }
  },
  "exp": 1408639878
}
Claim Required Description
client ✗ (not required for REST API) The client connection's ID provided by the JavaScript client after the 'open' event
channel Channel's ID that the token is for
permissions A regular expression JSON hash that defined permissions to publish and subscribe to rooms
exp Unix timestamp expiration time after which the token will not be accepted for processing
data Custom JSON data for the connection client. Used for observable rooms.

Permissions

The permissions claim is used to define which rooms the authenticated user can subscribe or publish to. It is possbile to define very detailed permission rules using regular expressions. Scaledrone uses the popular Perl regular expressions syntax used by most popular programming languages.

Example permissions:

"permissions": {
  ".*": {
    "publish": true,
    "subscribe": true
  },
  "^main-room$": {
    "publish": false,
    "subscribe": false
  }
}

This allows the user to publish and subscribe to all rooms (regex: .*) besides 'main-room' (regex: ^main-room$").

To match a room called 'main' the correct regex is '^main$' not 'main'. Otherwise it will match any room that contains the string 'main'.

JavaScript Authentication

JavaScript Authentication works by sending the drone.clientId to your authentication server that will generate a JWT containing the client claim along with the client's permissions. This token is then used to authenticate the client.

drone.authenticate() function is used to authenticate the JavaScript client with the generated JWT.

drone.on('open', function (error) {
  if (error) return console.error(error);
  // Get a clientId specific JWT from your authentication server 
  getJwt(drone.clientId, function (jwt) {
    // Authenticate the client using the token
    drone.authenticate(jwt);
  });
});

drone.on('authenticate', function (error) {
  if (error) return console.error(error);  
  // Client is now authenticated and ready to start working
});

drone.authenticate() can be called multiple times to update the client's permissions. The authenticate event will be emitted after each authentication, the open event is only emitted the first time. Keep in mind that when revoking any permissions the client will not automatically be kicked out of any rooms.

REST Authentication

REST requests are authenticated using a JSON Web Token set as a header's Bearer token:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

Example POST request

POST

URL:
    https://api2.scaledrone.com/[channel_id]/[room_name]/publish
Data:
    {"hello": "from REST, now with Auth!"}
Headers:
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjaGFubmVsIjaibTdMWGVXVWlnN1FtWE1xVyIsInB1Ymxpc2giOnRydWUsImV4cCI6MjgxNjQwMzkxMzI2MH0.LKkmfbbwSol-veSanJaIOEI1trlDU9LbfrOHuAEb0Vo
Don't set a client claim for REST API's JWT.

Example JWT Authentication Server

Example JWT server using Node.js can be found on GitHub.