Generate JWT from EBS

I want to send an Extension PubSub Message

I’m able to use that endpoint copy pasting JWT token printed in console when testing my extension frontend. Now I want to create a JWT from my EBS and use it to use the same endpoint. I’m always getting error 403 JWT could not be verified.

Reading from docs

if I’m not wrong I need to create a JWT with this structure:

  "exp": at least 1 hour from now(),
  "user_id": my twitch id,
  "role": "external"

Then signing this with my extension secret located here (it is Base64)

and “using your JWT library of choice”.
I’m using this since is in C++ and is header only library:

So this is the code I’m using to create the token:

auto token = jwt::create()
	.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{ 3600 })
	.set_payload_claim("user_id", jwt::claim(std::string("MY TWITCH ID")))
	.set_payload_claim("role", jwt::claim(std::string("external")))
	.sign(jwt::algorithm::hs256{ TWITCH_EXT_SECRET}); //<--string of base64 secret from ext confing 

and finally using it into request header

request->addHeader("Authorization", "Bearer "+token);

Where am I wrong?

You did base64 decode the twitch extension secret first before passing it to the library?

I found out that I was using a wrong base64 decode algorithm, now I fixed it and I found out that I need to use this structure instead:

  "exp": as you wish (I put 1 hour),
  "channel_id": broadcaster id to which to send the message,
  "role": "external",
  "pubsub_perms": {
    "send": ["*"]

Thanks for the tip :wink:

Ah yeah wrong payload would do it, I was fixated on the usual suspect of “didn’t base 64 the secret first”

Yeah, that was my first try, but I was biased by the false correctness of the algorithm. :joy:

I’ve a question about PubSub from extension before closing this topic. Can a viewer, using some workaround with dev console, sends broadcast messages? Or only EBS and broadcaster (with JWT provided by Twitch itself) are allowed to do so?



Only a JWT generated with role external or role broadcast(er) is valid to cast with when signed with the extension secret.

Ok, clear and simple. Thanks a lot. We can close the topic for me.