What data am I sending wrong in this request to broadcast a message?

I am trying to send a message to pub sub to https://api.twitch.tv/extensions/message/${channelId}

The error is “JWT could not be verified”

I have seen other threads with this error, but the solutions have not worked for me so far

So I would like to know what I am doing wrong.

Here is my code

this.twitch.onAuthorized((auth)=>{
        this.Authentication.setToken(auth.token, auth.userId)
        this.sendMessage(auth.clientId, auth.channelId, auth.userId)
    
    
  })


sendMessage (clientId, channelId, userId) {
  const headers = {
    'Client-ID': clientId,
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + this.makeServerToken(channelId, userId),
  };

  const body = JSON.stringify({
    content_type: 'application/json',
    message: 'Hello',
    targets: ['broadcast'],
  });
  const request = axios({
    method: 'POST',
    url: `https://api.twitch.tv/extensions/message/${channelId}`,
    headers,
    data: body
  })
  return request
    .then(response => console.log(response))
    .catch(error => console.log(error.response))
}

makeServerToken(channelId, userId) {
  const payload = {
    exp: Math.floor(Date.now() / 1000) + serverTokenDurationSec,
    channel_id: channelId.toString(),
    user_id: userId.toString(), // I suppose this is the userId from before
    role: 'external',
    pubsub_perms: {
      send: ['broadcast'],
    },
  };
  return jsonwebtoken.sign(payload, base64.encode(secret), { algorithm: 'HS256' });

}

As you’re using onAuthorized, it looks like you’re attempting to do this on the client side? You can’t create tokens client side as that would mean exposing your secret which would be a huge security breach.

You should only be creating tokens on your EBS, and the user_id in the JWT isn’t “the userId from before”, it’s the id of the extension owner.

As you’re using onAuthorized , it looks like you’re attempting to do this on the client side? You can’t create tokens client side as that would mean exposing your secret which would be a huge security breach.

Yes, I am. Thank you very much.

You should only be creating tokens on your EBS, and the user_id in the JWT isn’t “the userId from before”, it’s the id of the extension owner.

I am the extension owner, shouldn’t the id from before be the same one, in this case in particular at least?
Even if It wouldn’t work for other cases

Edit: Does the API know the message coming from the front end?

If you’re the extension owner then yes you have to use your ID. but auth.userId isn’t your ID.

If you check the docs for onAuthorized https://dev.twitch.tv/docs/extensions/reference/#helper-extensions you’ll see that the userId field is an Opaque User ID. What you need to use is your actual Twitch ID.

Technically speaking if you correctly create a token the request would still work if made from the front end, but there’s no point trying as like I said previously it would be a security breach and your extension can’t be approved as you would even by violating your Developer Agreement by exposing your secret.

Whose user id is auth.userId?

How do I know mine? I can’t do anything,I’m going crazy

I tried GET https://api.twitch.tv/kraken/user but get an oauth token error.

I’m going to throw myself out the window

It’s yours, it’s just an Opaque ID, not an actual User ID.

Are you using a proper OAuth token? If you’re attempting to use anything from your extensions front end then that’s not an OAuth token and wont work.

If you want to get your Twitch ID you can use the endpoint specified here in the docs: Reference | Twitch Developers

You don’t have to use an OAuth token, you can simply use your client id, and specify your username as the login querystring param.

Thank you, get-users worked and my id is the same as my channel id.

Still is it really not possible to do a test of sending a message to myself from the front end?

is that not possible?

I need to hire somebody to help me getting started. (if you are willing please send me private message)

New edit: I am using postman now to make the request, using the proper client_id and still get

{
“error”: “Forbidden”,
“status”: 403,
“message”: “Error (403): JWT could not be verified”
}

new edit 2: I am verifying my token here http://jwt.io and it returns verified. Could it be that my channel is not live? I don’t know what to think anymore

This this:

Someone had a similar issue and the correct JWT format is covered there

Thank you. I think the problem is how I am encoding the secret. I generated the jwt token in http://www.jwt.io and with that it works.

For testing purposes I will leave it like that for now since the next messages will have to be sent from the EBS, so for now I don’t worry anymore

I tried that example before but I don’t know which library you use for jwt.sign so I installed https://www.npmjs.com/package/jwt-simple and it said “Uncaught TypeError: _jwtSimple2.default.sign is not a function” so for now I will leave it with it working with the token from that link, I hope the backend works better.

The thing is that it was in fact the problem in the token, and not some other issue that was returning the same error, so I can rest for now.

jsonwebtoken is a better/more general use module for signing and verifying.

You shouldn’t be encoding the secret, but base64 decoding the secret before you use it to sign.

Usually with this endpoint the problem is your payload you are signing.
Thats why I linked to a question asked also this week with a similar issue.

return jsonwebtoken.sign(payload, base64.encode(secret), { algorithm: ‘HS256’ });

That should be base64 DECODE.

You are double encoding your secret.