Twitch Extension Authentication via JWT and shared secret

I followed the guide here to authenticating my extension against my backend, but each time i do i get the error
“JsonWebTokenError: invalid signature”
I’ve created the shared secret, decoded it and used it to verify the token i received from my extension but still get the same error.
please see my code below for reference.
An assistance in fixing this asap will go a long way, as this has delayed our extension development.

  req: Request,
  res: Response,
  next: NextFunction,
): Promise<unknown> => {
  try {
    const { authorization } = req.headers;
    const splits = authorization.split(' ');

    const clientSecret = process.env.TWITCH_CLIENT_SECRET;
    const clientId = process.env.TWITCH_CLIENT_ID;

    if (!clientId || !clientSecret) {
      return GenericResponses.errorResponse(

    if (splits[0] !== 'Bearer' || !splits[1]) {
      return GenericResponses.errorResponse(res, GenericResponses.INVALID_TWITCH_TOKEN());
    const token = splits[1];

    const base64DecodedToken = Buffer.from(clientSecret, 'base64');


    // TODO: if token is expired, return an error here too
    jwt.verify(token, base64DecodedToken, { algorithms: ['HS256'] });

    return next();
  } catch (e) {
    defaultLogger.error('error is ', e);
    return GenericResponses.errorResponse(res, ApiAccessResponses.UNAUTHORISED());

You used the wrong secret. based on the name

You need the Extension secret not the client secret
The bottom key not the top API Client Secret: in this screenshot

actually the name is wrong, but that is the value stored in that env variable.

Then as long as you copied and pasted the entire thing. (sometimes a copy/paste will miss characters if not quite paying attention)

And your frontend passed up the correct token (the authToken not the helixToken)

Then the other thing to do is to check that the recieved variables on your server are what you expect.
And check the time on the recieving server is accurate.

After that theres not many other things it could be unless you have a second extension and loaded in the wrong extension secret


Please do not leak your secret!

its a demo extension for test purposes i was going to delete anyways.
but thanks noted.

if you delete it liekly will not release the name to the pool to be used.

So you should just hang on to it rather than delete!

or use it for further testing

So, how do i resolve this issue with authentication?

Did you check/try these other steps?

I’ve checked all this. All seems fine

Then I’m out of ideas.

Your logic matches what I run in production and matches (close enough) to what I have in this working example extension

You can also try manually validating it using the Debugger on

Ok, i’ll take a look at this. Thanks

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.