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_type("JWT")
.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 
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. 
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?
No
Correct.
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.