Extension Chat Message | Unauthorized 401

Hi guys,

I am having troubles trying to send Chat Message from my EBS.
I think it’s something to do with the JWT, but I am not sure (I read the Docs a few times).
I keep getting Unauthorized 401.

I am on the local test.

the output request I am sending:

headers:
Authorization:“Bearer REMOVED”
Client-ID:“oy74nvst8rn5onmfl4sw00xcq950md”
content-length:37
Content-Type:“application/json”

href:“https://api.twitch.tv/extensions/oy74nvst8rn5onmfl4sw00xcq950md/0.0.7/channels/172995208/chat

My code:
(Node.js)

const client_id = CONFIG.twitchext_options.client_id;

const exp = (Date.now() + (3 * 60 * 1000));
const jwt_secret_base64 = Buffer.from(VARIABLES.jwt_secret).toString(‘base64’);
const payload = { channel_id: channel_id, role: “external”, “exp”: exp };
const signedToken = jwt.sign(payload, jwt_secret_base64);

const headers = {
‘Authorization’: 'Bearer ’ + signedToken,
‘Client-ID’: client_id,
‘Content-Type’: ‘application/json’
};

const dataString = ‘{ “text”: “This is a chat message.” }’;

const options = {
url: https://api.twitch.tv/extensions/${client_id}/${extVersion}/channels/${channel_id}/chat,
method: ‘POST’,
headers: headers,
body: dataString
};

function callback(error, response, body) {
console.log(‘response’, response.statusCode, response.statusMessage);
console.log(error);
console.log(body);
}

request(options, callback);

Any idea how to solve it / debug it? I am really lost :tired_face:
Thanks in advance!

Try:

const payload = { channel_id: ‘’+channel_id, role: “external”, “exp”: exp };

to make sure that channel_id is a cast to a string rather than an integer.

I tried, unfortunately, it didn’t help :\

const payload = { “channel_id”: “”+channel_id, “role”: “external”, “exp”: exp };

Any other suggestions?

What is the error message you are getting? (not just the code, but the JSON response)

body:“{“error”:“Unauthorized”,“status”:401,“message”:“authentication failed”}”

Signed JWT created by the EBS, following the requirements documented in Signing the JWT (in Building Extensions ) or Twitch JWT containing the broadcaster role. The channel_id inside the JWT must match the channel ID in the request URL.

const payload = { channel_id: ‘’+channel_id, role: “broadcaster”, “exp”: exp };

That should do it

@BarryCarlyon really appreciate the help!

I tride:

const payload = { “channel_id”: “”+channel_id, “role”: “broadcaster”, “exp”: exp };

but it still no luck… :astonished:

Signed JWT created by the EBS, following the requirements documented in Signing the JWT (in Building Extensions ) or Twitch JWT containing the broadcaster role. The channel_id inside the JWT must match the channel ID in the request URL.

But doesn’t it means that I need to use a JWT that I sign on my EBS (and according to the docs in “Building Extensions” it means to use “role”: “external”), OR to use a different Twitch JWT that already contains the broadcaster role?

const fs = require('fs');
const request = require('request');
const jwt = require('jsonwebtoken');

        let twitch_id = 'destination_channel_id';
        let version = '0.0.1';

        var secret = Buffer.from(secret, 'base64');

        var payload = {
            'exp':          Math.floor(new Date().getTime() / 1000) + 60,
            'user_id':      ''+twitch_id,
            'role':         'broadcaster'
        }

        var sig = jwt.sign(payload, secret);

        // tell everyone
        var payload = JSON.stringify({
            'text': 'Test'
        });

		let url = 'https://api.twitch.tv/extensions/'
            + client_id + '/'
            + version
            + '/channels/'
            + twitch_id
            + '/chat';

        request.post({
            url: url,
            headers: {
                'Accept': 'application/vnd.twitchtv.v5+json',
                'Authorization': 'Bearer ' + sig,
                'Client-ID': client_id,
                'Content-Type': 'application/json'
            },
            body: payload,
            gzip: true
        }, function(e, r, b) {
            if (e) {
                console.log(e);
            } else if (r.statusCode == 204) {
                console.log('Relay chat OK');
            } else {
                console.log('Got ' + r.statusCode);
                console.log(b);
            }
        });

Worked for me

image

It is worth noting, that I was getting auth errors till I reliased, I was sending to a channel that did not have the (in this case) panel in an active slot.

Please check that the extension version you are testing with

  • Has chat capabilities enabled
  • that version is installed
  • that version is active in one of the six slots
1 Like

@BarryCarlyon you’re awesome!
Thanks for the detailed example, it really helped and I got it working!

Apparently, I needed to use user_id in the JWT and NOT channel_id as written in the documentation.

BTW, both “role”: “external” and “role”: “broadcaster”, seems to work.

Worth noting I used jwt.io to decode the example bearer.

The example contains both channel_id and user_id tis just a little odd

mentions using user_id

I think it’s supposed to be

  • user_id of you (the extension developer)
  • channel_id of the destination channel

Docs probably need a tinker since it works with JUST user_id or could be a derp/bug twitch side in what you really need.

1 Like