Issuing Sync Tokens

In any Sync application, your work will span two components.

  • An SDK-driven client app (browser, iOS, Android), where users interact with Sync objects.
  • A backend server which vouches for your users' identities by providing Access Tokens.

Since any Twilio SDK-driven app requires an Access Token to run, most will have code like the below to retrieve a token.

function fetchAccessToken(handler) {
  // We use jQuery to make an Ajax request to our server to retrieve our 
  // Access Token
  $.getJSON('/token', function(data) {
      // The data sent back from the server should contain a long string, which
      // is the token you'll need to initialize the SDK. This string is in a format
      // called JWT (JSON Web Token) - more at http://jwt.io
      console.log(data.token);

      // Since the starter app doesn't implement authentication, the server sends
      // back a randomly generated username for the current client, which is how
      // they will be identified while sending messages. If your app has a login
      // system, you should use the e-mail address or username that uniquely identifies
      // a user instead.
      console.log(data.identity);

      handler(data);
  });
}

In this guide, we'll examine how to handle this request on the server and create a valid token for the client.

Minting an Access Token in your Backend

On the server we must decide, based on the token request that was sent to us, who the user is and what they should be allowed to do. To do this you might use your existing login system (using session cookies, an API token, or whatever mechanism you use to secure API requests or pages today). You might not care who a user is at all, and assign them a temporary identity. Who the user is and how you determine that will vary from app to app.

Assuming that the requesting user is authorized, your backend should respond with a signed token. Here's an example of generating those tokens in Node.js.

require('dotenv').load();
var http = require('http');
var path = require('path');

//You'll need an edge version of the Twilio NODE JS helper library during the Sync beta lifecycle
var AccessToken = require('twilio').jwt.AccessToken;
var SyncGrant = AccessToken.SyncGrant;
var express = require('express'); 

// Create Express webapp
var app = express();
app.use(express.static(path.join(__dirname, 'public')));

/*
Generate an Access Token for a Sync application user - it generates a random
username for the client requesting a token, and takes a device ID as a query
parameter.
*/
app.get('/token', function(request, response) {

    // 
    // This is the most critical part of your backend code, as you must identify the user and (possibly)
    // challenge them with some authentication scheme. To determine the identity, you might use:
    //    * A session datum consistently identifying one anonymous visitor,
    //    * A session key identifying a logged-in user
    //    * OAuth credentials identifying a logged-in user
    //    * A random username for all comers.
    //
    var identity = authenticatedSenderOf(request);

    // Create a "grant" identifying the Sync service instance for this app.
    var syncGrant = new SyncGrant({
        serviceSid: process.env.TWILIO_SYNC_SERVICE_SID,
    });

    // Create an access token which we will sign and return to the client,
    // containing the grant we just created and specifying his identity.
    var token = new AccessToken(
        process.env.TWILIO_ACCOUNT_SID,
        process.env.TWILIO_API_KEY,
        process.env.TWILIO_API_SECRET
    );
    token.addGrant(syncGrant);
    token.identity = identity;

    // Serialize the token to a JWT string and include it in a JSON response
    response.send({
        identity: identity,
        token: token.toJwt()
    });
});

// Create http server and run it
var server = http.createServer(app);
var port = process.env.PORT || 3000;
server.listen(port, function() {
    console.log('Express server running on *:' + port);
});

Applying the minted token to your SDK

Access Token in hand, we can now initialize the Sync SDK on the client to start doing fun stuff like subscribing to Sync objects. Here's how you would use the token string to initialize the client in JavaScript.

fetchAccessToken(initializeSync);

function initializeSync(tokenResponse) {
  var syncClient = new Twilio.Sync.Client(tokenResponse.token);

  // Use syncClient here
}

After you've initialized the client, you can access all of the SDK's features.

Handling Token Expiry

If required, an AccessManager object can be used to manage token lifecycle changes such as expiry. First, include the Twilio Common library:

<script src="https://media.twiliocdn.com/sdk/js/common/v0.1/twilio-common.min.js"></script>

Twilio Common Docs

Then, initialize the access manager:

  var accessManager = new Twilio.AccessManager(tokenResponse.token);

  //Note that the token expiry event fires on the access manager, not your Sync client
  accessManager.on('tokenExpired', refreshToken);   

  function refreshToken() {
    fetchAccessToken(setNewToken);
  }

  //Give Access Manager the new token
  function setNewToken(tokenResponse) {
    accessManager.updateToken(tokenResponse.token);
  }
  //Need to update the Sync Client that the accessManager has a new token
  accessManager.on('tokenUpdated', function() {
    syncClient.updateToken(tokenResponse.token);
});

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.