I am trying to pull some statistics for a TaskQueue using the TaskRouter.js SDK. For this I need to generate a capability router token, which allows access to the TaskQueue. According to the sample at twilio docs, I am supposed to pass null as the channel parameter(look in C# .Net sample), to generate the TaskRouterCapability token. But when I do this, I get an exception (object is null in get_Claims).
Looking at the source code, I should pass in the TaskQueue Sid as the channel id instead of null. When I did this a token was correctly generated.
To start off, am using the basic token generation example code at twilio docs :
class Program {
    static void Main(string[] args)
    {
        // Find your Account Sid and Auth Token at twilio.com/console
        const string accountSid = "ACbe0c12d747XXXXXXXXXXXXXXXXXb";
        const string authToken = "your_auth_token";
        const string workspaceSid = "WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string taskQueueSid = "WQXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var urls = new PolicyUrlUtils(workspaceSid, taskQueueSid);
        var allowFetchSubresources = new Policy($"{urls.TaskQueue}/**",
                                                HttpMethod.Get);
        var allowUpdates = new Policy(urls.TaskQueue, HttpMethod.Post);
        var policies = new List<Policy>
    {
        allowFetchSubresources,
        allowUpdates
    };
        // By default, tokens are good for one hour.
        // Override this default timeout by specifiying a new value (in seconds).
        // For example, to generate a token good for 8 hours:
        var capability = new TaskRouterCapability(
            accountSid,
            authToken,
            workspaceSid,
            null,
            policies: policies,
            expiration: DateTime.UtcNow.AddSeconds(28800) // 60 * 60 * 8
            );
        Console.WriteLine(capability.ToJwt());
    } }
class PolicyUrlUtils {
    const string taskRouterBaseUrl = "https://taskrouter.twilio.com";
    const string taskRouterVersion = "v1";
    readonly string _workspaceSid;
    readonly string _taskQueueSid;
    public PolicyUrlUtils(string workspaceSid, string taskQueueSid)
    {
        _workspaceSid = workspaceSid;
        _taskQueueSid = taskQueueSid;
    }
    public string TaskQueue => $"{Workspace}/TaskQueue/{_taskQueueSid}";
    string Workspace =>
        $"{taskRouterBaseUrl}/{taskRouterVersion}/Workspaces/{_workspaceSid}"; 
}
This gives me an exception on the last line(capability.ToJwt()). Exception is:
System.NullReferenceException occurred
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=<Cannot evaluate the exception source>
  StackTrace:
   at Twilio.Jwt.Taskrouter.TaskRouterCapability.get_Claims()
   at Twilio.Jwt.BaseJwt.ToJwt()
   at DeleteMe.Program.Main(String[] args) in D:\Projects\DeleteMe\DeleteMe\Program.cs:line 46
Now, I looked at the source code of TaskRouterCapability at twilio-csharp github, and seems to be the queue sid should be passed as the channel parameter. When I do this, the token is created. So I took the token generated here, and put it into this HTML file:
<html>
<head>
    <script type="text/javascript" src="https://media.twiliocdn.com/taskrouter/js/v1.11/taskrouter.min.js"></script>
    <script type="text/javascript">
        var taskQueue = new Twilio.TaskRouter.TaskQueue("token generated by console application");
        taskQueue.on("ready", function (taskQueue) {
            console.log(taskQueue.sid)                // 'WQxxx'
            console.log(taskQueue.friendlyName)       // 'Simple FIFO Queue'
            console.log(taskQueue.targetWorkers)      // '1==1'
            console.log(taskQueue.maxReservedWorkers) // 20
        });
    </script>
</head>
<body>
</body>
This then gives me some messages in the console:
taskrouter.min.js:1 Websocket opened: wss://event-bridge.twilio.com/v1/wschannels/ACxxxxxxxxxxxxxx/WQxxxxxxxx?token=eyJh.....&closeExistingSessions=false taskrouter.min.js:1 Received a message of type [connected] taskrouter.min.js:1 POST https://event-bridge.twilio.com/v1/wschannels/ACxxxxxxxxx/WQxxxxxxxxxxx 403 (Policies defined such that we cannot access the given resource)
So the connected event is called, but the ready event never happens.
Turns out there are 2 errors in the sample:
The channel parameter of TaskRouterCapability constructor should be passed the TaskQueue Sid rather than null. A value of null causes an Exception System.NullReferenceException occurred HResult=0x80004003 Message=Object reference not set to an instance of an object. Source= StackTrace: at Twilio.Jwt.Taskrouter.TaskRouterCapability.get_Claims() at Twilio.Jwt.BaseJwt.ToJwt()
There is a typo in the TaskQueue property of PolicyUrlUtils. The URL should have TaskQueues instead of TaskQueue
Have submitted a pull request for the same https://github.com/TwilioDevEd/api-snippets/pull/539
User contributions licensed under CC BY-SA 3.0