Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Verification fails for "event trigger" (but passed for "event verify-subscription") - regression in 1.1.23 against the 1.1.22 #329

Closed
abaksha-sc opened this issue Jul 1, 2024 · 3 comments · Fixed by #330

Comments

@abaksha-sc
Copy link

abaksha-sc commented Jul 1, 2024

What is the problem?

I just taken the code from official example: https://dev.twitch.tv/docs/eventsub/handling-webhook-events/#simple-nodejs-example
And only changed the secret to "TestTwitchWebhookSecret".

The result - command "event verify-subscription" successfully passed but "event trigger" fails.

Twitch CLI version : twitch-cli_1.1.23_Windows_x86_64
Operating System: Windows 10
Architecture Version: x64

Steps to reproduce

Trimmed from here: https://dev.twitch.tv/docs/eventsub/handling-webhook-events/#simple-nodejs-example

  1. Create a new project with npm init
  2. Run npm install express --save
  3. Create a file and name it app.js with the following content (here is only the secret is changed):
Click me - code is here
const crypto = require('crypto')
const express = require('express');
const app = express();
const port = 8080;
    
// Notification request headers
const TWITCH_MESSAGE_ID = 'Twitch-Eventsub-Message-Id'.toLowerCase();
const TWITCH_MESSAGE_TIMESTAMP = 'Twitch-Eventsub-Message-Timestamp'.toLowerCase();
const TWITCH_MESSAGE_SIGNATURE = 'Twitch-Eventsub-Message-Signature'.toLowerCase();
const MESSAGE_TYPE = 'Twitch-Eventsub-Message-Type'.toLowerCase();

// Notification message types
const MESSAGE_TYPE_VERIFICATION = 'webhook_callback_verification';
const MESSAGE_TYPE_NOTIFICATION = 'notification';
const MESSAGE_TYPE_REVOCATION = 'revocation';

// Prepend this string to the HMAC that's created from the message
const HMAC_PREFIX = 'sha256=';

app.use(express.raw({          // Need raw message body for signature verification
    type: 'application/json'
}))  


app.post('/eventsub', (req, res) => {
    let secret = getSecret();
    let message = getHmacMessage(req);
    let hmac = HMAC_PREFIX + getHmac(secret, message);  // Signature to compare

    if (true === verifyMessage(hmac, req.headers[TWITCH_MESSAGE_SIGNATURE])) {
        console.log("signatures match");

        // Get JSON object from body, so you can process the message.
        let notification = JSON.parse(req.body);
        
        if (MESSAGE_TYPE_NOTIFICATION === req.headers[MESSAGE_TYPE]) {
            // TODO: Do something with the event's data.

            console.log(`Event type: ${notification.subscription.type}`);
            console.log(JSON.stringify(notification.event, null, 4));
            
            res.sendStatus(204);
        }
        else if (MESSAGE_TYPE_VERIFICATION === req.headers[MESSAGE_TYPE]) {
            res.set('Content-Type', 'text/plain').status(200).send(notification.challenge);
        }
        else if (MESSAGE_TYPE_REVOCATION === req.headers[MESSAGE_TYPE]) {
            res.sendStatus(204);

            console.log(`${notification.subscription.type} notifications revoked!`);
            console.log(`reason: ${notification.subscription.status}`);
            console.log(`condition: ${JSON.stringify(notification.subscription.condition, null, 4)}`);
        }
        else {
            res.sendStatus(204);
            console.log(`Unknown message type: ${req.headers[MESSAGE_TYPE]}`);
        }
    }
    else {
        console.log('403');    // Signatures didn't match.
        res.sendStatus(403);
    }
})
  
app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
})


function getSecret() {
    // !!! THE SECRET CHANGED !!!!
    return 'TestTwitchWebhookSecret';
    // !!! THE SECRET CHANGED !!!!
}

// Build the message used to get the HMAC.
function getHmacMessage(request) {
    return (request.headers[TWITCH_MESSAGE_ID] + 
        request.headers[TWITCH_MESSAGE_TIMESTAMP] + 
        request.body);
}

// Get the HMAC.
function getHmac(secret, message) {
    return crypto.createHmac('sha256', secret)
    .update(message)
    .digest('hex');
}

// Verify whether our hash matches the hash that Twitch passed in the header.
function verifyMessage(hmac, verifySignature) {
    return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(verifySignature));
}
  1. Run node app.js
  2. Run Twitch CLI command twitch event verify-subscription channel.raid -F http://localhost:8080/eventsub -s TestTwitchWebhookSecret and check that it's successful.
  3. Then run Twitch CLI command twitch event trigger channel.raid -F http://localhost:8080/eventsub -s TestTwitchWebhookSecret - it fails

image

Relevant log output

c:\__Work\twitch-cli_1.1.23_Windows_x86_64>twitch event verify-subscription channel.raid -F http://localhost:8080/eventsub -s TestTwitchWebhookSecret
✔ Valid response. Received challenge 888003fe-92ec-88a5-3355-c4facddf9265 in body
✔ Valid content-type header. Received type text/plain with charset utf-8
✔ Valid status code. Received status 200

c:\__Work\twitch-cli_1.1.23_Windows_x86_64>twitch event trigger channel.raid -s TestTwitchWebhookSecret -F http://localhost:8080/eventsub
✗ Invalid response. Received Status Code: 403
✗ Server Said: Forbidden
{"subscription":{"id":"","status":"enabled","type":"channel.raid","version":"1","condition":{"to_broadcaster_user_id":"22473690"},"transport":{"method":"webhook","callback":"null"},"created_at":"2024-07-01T15:27:01.4937421Z","cost":0},"event":{"to_broadcaster_user_id":"22473690","to_broadcaster_user_login":"testBroadcaster","to_broadcaster_user_name":"testBroadcaster","from_broadcaster_user_id":"57779910","from_broadcaster_user_login":"testFromUser","from_broadcaster_user_name":"testFromUser","viewers":78266}}
@abaksha-sc
Copy link
Author

UPD: works fine in version 1.1.22. So seems the regression issue is actual only for 1.1.23:

image

@abaksha-sc abaksha-sc changed the title [Bug] Verification fails for "event trigger" but passed for "event verify-subscription" [Bug] Verification fails for "event trigger" (but passed for "event verify-subscription") - regression in 1.1.23 against the 1.1.22 Jul 1, 2024
@chticer
Copy link

chticer commented Jul 1, 2024

Can reproduce the same issue on 1.1.23 but not with 1.1.22.

WindowsTerminal_DEr8NMuUzY

@BarryCarlyon
Copy link
Contributor

BarryCarlyon commented Jul 2, 2024

Both verify and trigger:

  • postbody.subscription.id is blank instead of populated
  • header['twitch-eventsub-message-id'] is blank instead of populated

So I suspect the commits in #322 are the fault

@BarryCarlyon BarryCarlyon mentioned this issue Jul 2, 2024
4 tasks
@Xemdo Xemdo closed this as completed in #330 Jul 4, 2024
@Xemdo Xemdo closed this as completed in 2b10cc2 Jul 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants