Eventsub: Twitch dont reach my callback url

Hi guys!
Currently Im integrating the eventsub webhooks in my platform, but i have the next issue:

  1. All flow for enable a sub is successfully locally, the events shoots successfully locally too (all works correclty with ngrok locally).
  2. When I test this in my server twitch dont send me the requests to callback url, and the sub status is webhook_callback_verification_failed
  3. I see the logs of my server and the url callback never is requested for twitch with the challenge. My server have ssl enabled in 443 port, the url callback is: https://watcher.gantzerbot.xyz/notification

for complete the info, below I attach the nginx configuration:

upstream botcore {
    server first:8000;
}

upstream botcorenode {
    server second:3000;
}

server {
    listen 80;
    server_name gantzerbot.xyz www.gantzerbot.xyz;

    return 301 https://gantzerbot.xyz$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.gantzerbot.xyz;
    ssl_certificate /path/to/cert;
    ssl_certificate_key /path/to/cert;

    return 301 https://gantzerbot.xyz$request_uri;
}

server {
    listen 443 ssl http2;
    server_name gantzerbot.xyz;
    proxy_connect_timeout 20s;
    proxy_send_timeout 20s;
    ssl_certificate /path/to/cert;
    ssl_certificate_key /path/to/cert;

    location / {
        proxy_pass http://botcore;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;

        client_max_body_size 100M;
    }

    location /static/ {
        alias /code/staticfiles/;
        add_header Pragma public;
        add_header Cache-Control "public";
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Max-Age 3600;
        add_header Access-Control-Expose-Headers Content-Length;
        add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
    }

    location /media/ {
        alias /code/media/;
        add_header Pragma public;
        add_header Cache-Control "public";
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Max-Age 3600;
        add_header Access-Control-Expose-Headers Content-Length;
        add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
    }
}

server {
    listen 80;
    server_name watcher.gantzerbot.xyz ;

    return 301 https://watcher.gantzerbot.xyz$request_uri;
}

server {
    listen 443 ssl http2;
    server_name watcher.gantzerbot.xyz;
    ssl_certificate /path/to/cert;
    ssl_certificate_key /path/to/cert;

    location / {
        proxy_pass http://botcorenode;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        #proxy_set_header Host $host;
        proxy_set_header Host watcher.gantzerbot.xyz;
        client_max_body_size 100M;
        proxy_set_header Access-Control-Allow-Origin https://watcher.gantzerbot.xyz;
	    proxy_set_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,X-Requested-With,Accept,Content-Type, Origin';
        proxy_set_header X-NginX-Proxy true;
        proxy_redirect off;
    }

I dont show other parts of code because this dont work in the server locally run perfect so i think that maybe the problem is in the nginx config.

Thanks in advance

Regards :smiley:

I recieved a 403 from your callback URL

Usong the TwitchCLI to test https://github.com/twitchdev/twitch-cli/blob/main/docs/event.md#verify-subscription

twitch event verify-subscription cheer -F https://watcher.gantzerbot.xyz/notification
✗ Invalid response. Received Forbidden as body, expected c85aee50-fff5-9ce5-2a89-b097082c477e
✗ Invalid status code. Received 403, expected a 2XX status

Looking at your NGINX config I don’t see anything in patciular wrong. It is similar to my own configs.

Hi!

According to my implementation, the only way to get a 403 error is when the signature is invalid, the problem is that doing manual tests the endpoint works like this, returning a 403 error, but when it comes to doing the complete flow creating the sub, twitch don’t request my callback url with the signature, in the nginx logs, i see that twitch dont request the callback url.

app.post('/notification', (req, res) => {

    console.log("xxxxxxxxxxx type BEFORE", req.header("Twitch-Eventsub-Message-Type"))

    if (!verifySignature(req.header("Twitch-Eventsub-Message-Signature"),

            req.header("Twitch-Eventsub-Message-Id"),

            req.header("Twitch-Eventsub-Message-Timestamp"),

            req.rawBody)) {

                console.log("xxxxxxxxxxx type FAIL", req.header("Twitch-Eventsub-Message-Type"))

        res.status(403).send("Forbidden") // Reject requests with invalid signatures

    } else {

        console.log("xxxxxxxxxxx type", req.header("Twitch-Eventsub-Message-Type"))

        if (req.header("Twitch-Eventsub-Message-Type") === "webhook_callback_verification") {

            originalBody = req.body

            if (req.body !== undefined){

                message = req.body.subscription.id + req.body.subscription.created_at + req.body

                signature = crypto.createHmac('sha256', secretito).update(message) // Remember to use the same secret set at creation

                expectedSignatureHeader = "sha256=" + signature.digest("hex")

            }

            parameters = {

                subscription: req.body.subscription,

                id: req.body.subscription.id,

                timestamp: req.body.subscription.created_at,

                sub_type: req.body.subscription.type,

                challenge: req.body.challenge,

                broadcaster_user_id: req.body.subscription.condition.broadcaster_user_id,

                signature: expectedSignatureHeader,

                rawBody: originalBody,

                access_token: access_token

            }

            axios.post(

                django_backend + "/activate-subscription",

                parameters

            )

            .then((response) => {

                res.send(req.body.challenge) 

            })

        } else if (req.header("Twitch-Eventsub-Message-Type") === "notification") {

            if (req.body.subscription.type == "channel.follow"){

                axios.post(

                    django_backend + "/shoot-ws",

                    {

                        uid: req.body.event.broadcaster_user_id,

                        viewer: req.body.event.user_name,

                        streamer: req.body.event.broadcaster_user_login,

                        content_type: req.body.subscription.type,

                        redemption: {

                            user_input: "",

                            redeemer_user: "",

                            redepmtion_id: "",

                            reward_id: ""

                        },

                        content_raw: "",

                        content_message: "",

                        access_token: access_token

                    }

                )

                .then((response) => {

                    res.send(req.body.event)

                })

            }

        }

    }

})

for now, i’ll go to make tests with the lib that you are use (twitch-cli) for discover the reason of this behavior, thanks for your help!! <3

The issue might be because you are using capitals in your req.header calls and/or using a function call instead of an array

Depending on what req is.

This nodeJS/express example might be of use https://github.com/BarryCarlyon/twitch_misc/blob/main/eventsub/handlers/nodejs/receive.js

Nope, still not working, locally works with capitalize and without capitalize, while in production dont works :frowning: i’ll continue with tests of this if i find a solution i’ll tell you in this thread.

Hi, problem resolved, the problem is for the cloudflare fight bot feature, this recognize a twitch like a bot and block requests provided from his servers, for that reason i dont saw the twitch requests in my nginx logs, cloudflare block requests before arrive to my server. :smiley: Thanks for you help <3

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