Can’t say I’ve used either of those tools for testing purposes so I don’t know if those achieve the expected results.
Here’s my example
// Lets prepare the signatures for saving config and sending to PubSub
// The EXP is being set to 60 seconds in the future
// which is a bit long but it suffices
const sigConfigPayload = {
"exp": Math.floor(new Date().getTime() / 1000) + 60,
"user_id": config.owner,
"role": "external",
}
const sigConfig = jwt.sign(sigConfigPayload, ext_secret);
const sigPubSubPayload = {
"exp": Math.floor(new Date().getTime() / 1000) + 60,
"user_id": config.owner,
"role": "external",
"channel_id": "all",
"pubsub_perms": {
"send": [
"global"
]
}
}
Granted this is for sending to “global” but it’s easy to modify for single channel
or if you want a channel example
const sigPubSubPayload = {
"exp": Math.floor(new Date().getTime() / 1000) + 60,
"user_id": config.extension.owner_id,
"role": "external",
"channel_id": channel_id,
"pubsub_perms": {
"send": [
"broadcast"
]
}
}
const sigPubSub = jwt.sign(sigPubSubPayload, config.extension.secret);
got({
url: 'https://api.twitch.tv/extensions/message/' + sigPubSubPayload.channel_id,
method: 'POST',
headers: {
"Client-ID": config.extension.client_id,
"Content-Type": "application/json",
"Authorization": "Bearer " + sigPubSub
},
body: JSON.stringify({
"message": JSON.stringify({
event: which,
data
}),
"content_type": "application/json",
"targets": sigPubSubPayload.pubsub_perms.send
}),
gzip: true
})
.then(resp => {
// Same story here with the rate limit its around 60 per minute per topic
console.error('Relay PubSub OK', channel_id, resp.statusCode, resp.headers['ratelimit-ratelimitermessagesbychannel-remaining'], '/', resp.headers['ratelimit-ratelimitermessagesbychannel-limit']);
})
.catch(err => {
if (err.response) {
console.error('Error', err.statusCode, err.response.body);
} else {
console.error('Generic Error', err);
}
})
config.extension.secret
is the base64 decoded secret
config.extension.secret = Buffer.from(config.extension.extension_secret, 'base64');
Edit: I did a test. generated a JWT via JWT.io and it posted successfully.
Final things to check
The extension is installed and active on the target channel?
You did copy/paste the whole secret and JWT.io didn’t report a “weak secret”?
The error doesn’t suggest these things, since it’s having and issue with your JWT as a whole
Test code:
const fs = require('fs');
const path = require('path');
const config = JSON.parse(fs.readFileSync(
path.join(
__dirname,
'config.json'
)
));
// prepare for use
config.extension.secret = Buffer.from(config.extension.extension_secret, 'base64');
const got = require('got');
var sigPubSub = 'FromJWTIO';
got({
url: 'https://api.twitch.tv/extensions/message/56410307',
method: 'POST',
headers: {
"Client-ID": config.extension.client_id,
"Content-Type": "application/json",
"Authorization": "Bearer " + sigPubSub
},
body: JSON.stringify({
"message": JSON.stringify({
event: 'test',
data: {}
}),
"content_type": "application/json",
"targets": ['broadcast']
}),
gzip: true
})
.then(resp => {
// Same story here with the rate limit its around 60 per minute per topic
console.error('Relay PubSub OK', 'test', resp.statusCode, resp.headers['ratelimit-ratelimitermessagesbychannel-remaining'], '/', resp.headers['ratelimit-ratelimitermessagesbychannel-limit']);
})
.catch(err => {
if (err.response) {
console.error('Error', err.statusCode, err.response.body);
} else {
console.error('Generic Error', err);
}
})