Access Token Lifecycle

Twilio access tokens have a lifetime determined by your server when you generate the token, with a maximum of 24 hours. When an access token in your application expires, you must update the token with your client(s) to continue using Twilio.

Twilio Client SDKs such as Chat and Sync take an access token as part of their initial parameters. They also offer a method to provide updated tokens over the lifetime of the client. For uninterrupted access to Twilio's services, you should provide renewed tokens to your Twilio client SDKs before expiration with the client's updateToken method.

Loading Code Samples...
Language
chatClient.updateToken(token, tokenUpdateListener);
chatClient.updateToken(token);
[chatClient updateToken:token completion:^(TCHResult *result) {
  if (![result isSuccessful]) {
    // warn the user the update didn't succeed
  }
}];
chatClient.updateToken(token) { (result) in
  if (!result.isSuccessful()) {
    // warn the user the update didn't succeed
  }
}
Updating Your Access Token

Twilio offers an optional helper, AccessManager, to manage this renewal process. The usage of this helper is:

  • Implement AccessManager's facility to be notified of tokens that have already expired or are about to.
  • Provide AccessManager with a copy of a token in use by one or more Twilio clients.
  • Instruct AccessManager how to update your client with a callback that will be called with a new token.

When a token is in its final three minutes, the token will expire method is called. If the token was not updated before its expiry, a token expired method will trigger. You should use this method to get a new access token and set it on the AccessManager, making sure to update the token. AccessManager will then trigger the update you provided and set a timer based on the new token's expire time.

The implementation of this varies by platform and is described in detail below.

Integration of AccessManager

AccessManager is optional and provided in the same manner as the first person client SDKs. How you use it depends on your platform.

Android

For Android, we distribute Access Manager using gradle and bintray.

iOS

For iOS, you can choose between CocoaPods or manual integration of the .framework file.

Javascript

For Javascript, you can integrate directly via npm, our website, or download and host the file yourself.

Loading Code Samples...
Language
// In your build.gradle, add AccessManager:
compile 'com.twilio:accessmanager-android:0.1.0'
let AccessManager = require('twilio-common').AccessManager;
// In your Podfile, add AccessManager:

use_frameworks!

target '...' do
  pod 'TwilioAccessManager', '~> 0.1.0'
end
// In your Podfile, add AccessManager:

use_frameworks!

target '...' do
  pod 'TwilioAccessManager', '~> 0.1.0'
end
Integrating the Access Manager Helper

Initialization

Your access token is passed to both AccessManager and your Twilio client(s). You also provide a block of code or method body to call upon token updates.

You should initialize both Access Manager and the Chat client with the same initial token. You can then either register an update lambda or implement a listener method depending on your platform. If you are using multiple Twilio client SDKs in your project that share a common access token with multiple service grants, you can register multiple update blocks here to renew each client.

Loading Code Samples...
Language
import com.twilio.accessmanager.AccessManager;

// This listener will receive AccessManager lifecycle update callbacks
listener = new Listener; // See below for implementation

// Listener we specify in the constructor is for token lifecycle events
// (onTokenWillExpire, onTokenExpired, onError)
accessManager = new AccessManager(accessToken, listener);
// Listener we specify with the additional call is for token update events
// (onTokenUpdated) - use this listener to update tokens on Twilio client(s)
accessManager.addTokenUpdateListener(listener);
let token = generateToken();

let accessManager = new AccessManager(token);
let chatClient = new ChatClient(token);

accessManager.on('tokenUpdated', am => {
  // get new token from AccessManager and pass it to the library instance
  chatClient.updateToken(am.token));
});
self.accessManager = [TwilioAccessManager accessManagerWithToken:token
                                                        delegate:self];
[TwilioChatClient chatClientWithToken:accessManager.currentToken
                           properties:properties
                             delegate:delegate
                           completion:(TCHResult *result, TwilioChatClient *client) {
  if ([result isSuccessful]) {
    self.client = client;
    __weak typeof(client) weakClient = client;
    [accessManager registerClient:client forUpdates:^(NSString *updatedToken) {
        [weakClient updateToken:updatedToken completion:^(TCHResult *result) {
          if (![result isSuccessful]) {
            // warn the user the update didn't succeed
          }
        }];
    }];
  }
 }];
self.accessManager = TwilioAccessManager.init(token: token, delegate: self)
TwilioChatClient.init(token: accessManager.token, properties: properties, delegate: delegate) { (result, client) in
  if (result.isSuccessful()) {
    self.client = client
    self.accessManager?.registerClient(client, forUpdates: { [weak client = self.client] (token) in
        client?.updateToken(token) { (result) in
          if (!result.isSuccessful()) {
            // warn the user the update didn't succeed
          }
        }
      })
  }
}
Initializing Access Manager

AccessManager Events

AccessManager will trigger an event three minutes before token expiry (on iOS, Android, and coming soon to JS) and at the time of token expiration. It is best to implement only one of these methods. A token error event may surface if there is a problem with the token provided to AccessManager.

If a token is used with less than three minutes remaining until expiry, the token expiring mechanism will be called immediately. If the token is already expired, the token-expiring call, as well as the "token expired" call, will trigger in that order.

Loading Code Samples...
Language
public class Listener
  implements
    AccessManager.Listener,
    AccessManager.TokenUpdateListener {

  // AccessManager.Listener - handle token lifecycle

  @Override
  public void onTokenWillExpire(AccessManager accessManager)
  {
    // Token will soon expire.
    // ...
    // Get new token here.
    // ...

    accessManager.updateToken(NEW_VALID_TOKEN);
    // accessManager will then update token and call onTokenUpdated()
  }

  @Override
  public void onTokenExpired(AccessManager accessManager)
  {
    // Token expired.
    // ...
    // Get new token here.
    // ...

    accessManager.updateToken(NEW_VALID_TOKEN);
  }

  @Override
  public void onError(AccessManager accessManager, String err)
  {
    // An error occured in the AccessManager
  }

  // AccessManager.TokenUpdateListener - update all components with new token
  // This is called by AccessManager when new token is available to update SDK
  // clients.

  @Override
  public void onTokenUpdated(String token)
  {
    // Update Twilio client(s) in this callback
    chatClient.updateToken(token, tokenUpdateListener);
  }

}
accessManager.on('tokenExpired', () => {
  // generate new token here and set it to the accessManager
  let updatedToken = generateToken(); 
  accessManager.updateToken(updatedToken);
});
- (void)accessManagerTokenWillExpire:(nonnull TwilioAccessManager *)accessManager {
    // ... obtain new token asynchronously
    [accessManager updateToken:token];
}
func accessManagerTokenWillExpire(_ accessManager: TwilioAccessManager) {
    // ... obtain new token asynchronously
    accessManager.updateToken(token)
}
Responding to Access Manager's Events

Regardless of the way you choose to update your client's access token, renewing the token prior to expiry is important for ensuring that your chat application is a great user experience.

Next: Error Handling and Diagnostics

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.

1 / 1
Loading Code Samples...
chatClient.updateToken(token, tokenUpdateListener);
chatClient.updateToken(token);
[chatClient updateToken:token completion:^(TCHResult *result) {
  if (![result isSuccessful]) {
    // warn the user the update didn't succeed
  }
}];
chatClient.updateToken(token) { (result) in
  if (!result.isSuccessful()) {
    // warn the user the update didn't succeed
  }
}
// In your build.gradle, add AccessManager:
compile 'com.twilio:accessmanager-android:0.1.0'
let AccessManager = require('twilio-common').AccessManager;
// In your Podfile, add AccessManager:

use_frameworks!

target '...' do
  pod 'TwilioAccessManager', '~> 0.1.0'
end
// In your Podfile, add AccessManager:

use_frameworks!

target '...' do
  pod 'TwilioAccessManager', '~> 0.1.0'
end
import com.twilio.accessmanager.AccessManager;

// This listener will receive AccessManager lifecycle update callbacks
listener = new Listener; // See below for implementation

// Listener we specify in the constructor is for token lifecycle events
// (onTokenWillExpire, onTokenExpired, onError)
accessManager = new AccessManager(accessToken, listener);
// Listener we specify with the additional call is for token update events
// (onTokenUpdated) - use this listener to update tokens on Twilio client(s)
accessManager.addTokenUpdateListener(listener);
let token = generateToken();

let accessManager = new AccessManager(token);
let chatClient = new ChatClient(token);

accessManager.on('tokenUpdated', am => {
  // get new token from AccessManager and pass it to the library instance
  chatClient.updateToken(am.token));
});
self.accessManager = [TwilioAccessManager accessManagerWithToken:token
                                                        delegate:self];
[TwilioChatClient chatClientWithToken:accessManager.currentToken
                           properties:properties
                             delegate:delegate
                           completion:(TCHResult *result, TwilioChatClient *client) {
  if ([result isSuccessful]) {
    self.client = client;
    __weak typeof(client) weakClient = client;
    [accessManager registerClient:client forUpdates:^(NSString *updatedToken) {
        [weakClient updateToken:updatedToken completion:^(TCHResult *result) {
          if (![result isSuccessful]) {
            // warn the user the update didn't succeed
          }
        }];
    }];
  }
 }];
self.accessManager = TwilioAccessManager.init(token: token, delegate: self)
TwilioChatClient.init(token: accessManager.token, properties: properties, delegate: delegate) { (result, client) in
  if (result.isSuccessful()) {
    self.client = client
    self.accessManager?.registerClient(client, forUpdates: { [weak client = self.client] (token) in
        client?.updateToken(token) { (result) in
          if (!result.isSuccessful()) {
            // warn the user the update didn't succeed
          }
        }
      })
  }
}
public class Listener
  implements
    AccessManager.Listener,
    AccessManager.TokenUpdateListener {

  // AccessManager.Listener - handle token lifecycle

  @Override
  public void onTokenWillExpire(AccessManager accessManager)
  {
    // Token will soon expire.
    // ...
    // Get new token here.
    // ...

    accessManager.updateToken(NEW_VALID_TOKEN);
    // accessManager will then update token and call onTokenUpdated()
  }

  @Override
  public void onTokenExpired(AccessManager accessManager)
  {
    // Token expired.
    // ...
    // Get new token here.
    // ...

    accessManager.updateToken(NEW_VALID_TOKEN);
  }

  @Override
  public void onError(AccessManager accessManager, String err)
  {
    // An error occured in the AccessManager
  }

  // AccessManager.TokenUpdateListener - update all components with new token
  // This is called by AccessManager when new token is available to update SDK
  // clients.

  @Override
  public void onTokenUpdated(String token)
  {
    // Update Twilio client(s) in this callback
    chatClient.updateToken(token, tokenUpdateListener);
  }

}
accessManager.on('tokenExpired', () => {
  // generate new token here and set it to the accessManager
  let updatedToken = generateToken(); 
  accessManager.updateToken(updatedToken);
});
- (void)accessManagerTokenWillExpire:(nonnull TwilioAccessManager *)accessManager {
    // ... obtain new token asynchronously
    [accessManager updateToken:token];
}
func accessManagerTokenWillExpire(_ accessManager: TwilioAccessManager) {
    // ... obtain new token asynchronously
    accessManager.updateToken(token)
}