What are JWT's signed with?

I assumed that JWT’s taken from onAuthorised were signed with the extension secret key but every time I try to verify with that key it comes back as a failure. Does anyone know what the actual signing token is?


Yes, the JWT is signed with the secret key of your extension.

Depending on what library you’re using or how you’ve implemented the signature verification, you might need to base64-decode the key prior to using it to verify the JWT.

You also need to use the correct hash algorithm for the verification.

Maybe it helps, here’s where my code does the actual verification of the JWT (PHP based EBS):

Thanks, I’ll give decoding a go.


What I noticed is that JWT token verification works if it the token comes from the production environment, but the token validation will fail if it is obtained from the developer rig (still waiting for a dev to confirm this bug).

I would be inclined to agree, I’m still on the rig and have not been able to validate once yet.

Did you put the extension secret (key) into the dev-rig config?

Yeah, I’ve put all the relevant data in.

I tested it with the same piece of validation code over the same secret. The validation works on production and doesn’t work on developer rig.

If anybody is able to validate the token that is returned by the developer rig please do post here.

How are you trying to validate the jwt? As far as i can tell there is no rig bug. The payload is signed with the secret and I am able to verify the signature on jwt.io consistently.

I think a possible gotcha here is that the secret given from the dev site is base64 encoded, so on jwt.io (or with whatever library you are using) you must make sure you check the button secret base64 encoded.

Additionally, I’ve used the jwt created from the rig to send messages to and from clients over Twitch Pubsub. As a general suggestion, when troubleshooting the rig, ensure you’ve pulled down the latest changes, clear local storage, and recreate the views.

Are you sure that’s working? If I try the JWT decoder on jwt.io, even with that checked, it fails. It looks like it passes only if you paste the token in then click in a different box, because the right side updates the token on the left to be valid. But on first paste, it’s invalid.

I have found the same behavior for the Viewers JWT generated by the local developer-rig. I’m not able to validate them.
However, I’m able to successfully validate the tokens generated for the broadcaster in the “live config” page. I’m validating this with the secret that I set up.

Is it possible that some tokens are generated using some default/hardcoded password?
I’ll try to find it out checking the developer’s rig code.

I have just seen that the token given to a “Logged-In Viewer” is signed with the default developer-rig secret.
Am I missing to add my custom password somewhere?

I believe you’re correct, broadcoaster tokens work for me, but not viewer.

It should:

If in local mode it’ll use the devRig secret.
If in live mode it’ll use your actual values

Actually I’ve just found this in the documentation.

However, the start script allows you to pass the secret as the parameter -s. This parameter is actually being taken into account when generating the token for the broadcaster. I don’t get why it is not being used for generating viewers tokens.

Which is for local mode.

Which is for live mode.

So in local mode it’s using the passed secret instead of the overridden rig secret for broadcaster tokens? Starting in Local mode, should ignore a passed secret really…

Yes, the secret used for generating broadcaster tokens in local mode is the one passed as -s parameter.

I’m using the following command to start up the developer rig in local mode:
yarn start -s bXlfc3VwZXJfUzNLcmVULVNVNEpKSg== -l ../panel.json

Just do

yarn start -l ../panel.json

For local mode.

You found a bug in the rig

Okay, so the expected behavior for local mode is to ignore the passed secret.

Would be useful if I open a PR in order to ignore the parameter?

I’m not sure if the rigs intention is to use the passed secret or ignore the passed secret in localmode.

Okay, so I’ll just run it without the parameter and everything should work fine :slight_smile: