twiliotwilio-functionstwilio-flex

Handling expired ssoTokenPayload when calling Twilio Functions from Flex Plugin


We have implemented a Twilio Flex plugin, basically allowing each user to supply some additional information (in a form) when they complete a task. Thus plugin has to fetch some task-related data prior to showing that form.

We use a Twilio Function for that, protecting it with Token Validator as described here. The plugin code (that invokes this function) looks like this:

export const getCallDuration = async (callSid, token) => {
  const response = await axios.post(FUNCTION_URL, {
    WorkspaceSid: WORKSPACE_SID,
    CallSid: callSid,
    Token: token,
  });
  return response.data.callInfo.duration;
};

// and here's the usage part:
const callDuration = await getCallDuration(
  task.attributes.call_sid,
  flexState.session.ssoTokenPayload.token,
);

... where flexState is basically a prop of the plugin component, and its value is set to manager.store.getState().flex when plugin is initialized.

Now, that works smoothly most of the time. The problem is, we start regularly receiving "Access Token has expired or expiration date is invalid" error closer to the end of the working day - as users tend to leave their browsers open for several hours, and not reauthenticate.

While Twilio Flex does know the session state:

enter image description here

... it seems to essentially do nothing about it, allowing the plugin to use an expired token.

The bigger concern is that the docs don't seem to mention any way to update that ssoTokenPayload manually whenever a token is expired. All the relevant parts seem to be about something different, not applicable to Flex.

I've done some search here at SO, and the closest one seems to be this thread which describes the same error, but for a different use case. AccessManager library, mentioned there, doesn't seem to be an option because it was essentially deprecated:

The AccessManager was used until mid 2016 then removed (and Conversations were deprecated). The AccessManager was useful when there was a long lived Video client, now you just call connect with a fresh token each time you want to join a room.

What's our options in this case?


Solution

  • It seems* that Twilio Flex 2.x attempts to renew its access token automatically. The good thing about it is that all the intricacies of the process are hidden from a developer, who shouldn't even care about AccessManager now.

    The not-so-obvious thing, however, is that the process, it seems, causes a typical Redux Store update - which doesn't make much sense to me, as token update should not trigger re-render... but anyway. So, if you're not careful about what you pass in props, your component will end up working with stale data.

    The most straightforward way out seems to be using "shortcut" to get access token, mentioned in this issue. In our case, we started passing manager as a component prop, to be used like this:

    const callDuration = await getCallDuration(
      task.attributes.call_sid,
      manager.user.token,
    );
    

    This alternative to manager.store.getState().flex.session.ssoTokenPayload.token doesn't seem to be documented, but it seems* to be fair to assume it will stay active.

    *It would have been great to be able to replace all the "it seems" in this post with direct links to Twilio Flex documentation. At the very least, "shortcut" of manager.user.token deserves to be mentioned in this part of Twilio Function usage guide.