Send PubSub message returning 403 JWT could not be verified


I’m using the following schema which is exactly what recommends in the docs to create the JWT schema:

data = {
“exp”: int(expire_date),
“user_id”: “%s” % config.TWITCH_USER_ID,
“role”: “external”,
“channel_id”: channelId,
“pubsub_perms”: {
“send”: ["*"]

Then im using the configuration extension secret to sign it, but it returns the 403. Weirdest thing is that this was working until not to long ago.

Has something changed or im doing something wrong?


Not sure what you are using to sign/verify and not sure if this is even related, but some libraries, such as the popular jsonwebtoken do not use a base64 encoded secret by default.

“…there are other libraries that expect base64 encoded secrets (random bytes encoded using base64), if that is your case you can pass Buffer.from(secret, ‘base64’), by doing this the secret will be decoded using base64 and the token verification will use the original random bytes.”


“channel_id”: channelId,

To string, you are passing a numeric


I was having the same issue. I was following the documentation but was getting that as well but when I did this below it worked for me.

const custom_options = {
    "jwt_secret": {
        "encoded": true, //default is to assume base64, will decode for you
        "expires": 1503343947, //for signing jwts
        "enabled": true, //enable below options
        "method":"path",//path to file that holds jwt_secret
        "location": "../../config/variables" //file with jwt_secret variable
    "client_id": "some client id",
    "client_secret": "some client secret"

const twitchext = require('twitchext-helper')(custom_options);

//can also be done with 'jsonwebtoken' module
var signedToken = twitchext.sign({
 channel_id: ""+channel_id,
 role: "external",
 pubsub_perms: {
 listen: [ 'broadcast' ], send: [ '*' ]

Not 100% sure why it worked but when i added that extra "listen: [‘broadcast’] in pubsub_perms it started working after that