Błędne wyliczenie funkcji hash_hmac() przy odbiorze webhooka z Tally.so

0

Cześć,
Tworzę swoją wtyczkę do Wordpress'a. Niestety poległem przy sprawdzaniu czy request pochodzi od serwera Tally.so (walidacja).

Mam metodę: IsWebhookTrusted()

        // Obliczamy oczekiwany podpis HMAC na podstawie klucza Tally i payloadu

        $payLoadBodyString = json_encode($payLoadBody);

        $expectedSignature = base64_encode( hash_hmac('sha256', $payLoadBodyString, $tallyKeyFromSettings, false) );
    
        error_log("Hash coming from request: " . $receivedSignature);
        error_log("Hash saved in settings: " . $tallyKeyFromSettings);

        error_log("Result of cryptographic count: " . $expectedSignature);

        // Result of comparison of the received hash with the desired one
        $result = hash_equals($receivedSignature, $expectedSignature);

        if( $result == true ) {
            // Consistent comparison OK
            error_log("Hash OK");
            return true;
        } else {
            // The comparison is inconsistent NOT OK
            error_log("Hash Invalid");
            return false;
        }
    }

Jako parametry otrzymuje ona klucz, który został wcześniej pobrany z Tally i jest trzymany w ustawieniach. Drugi argument funkcji czyli $receivedSignature jest pobierany z nagłówka http requestu, który przychodzi. Zgodnie z ich dokumentacją -> https://tally.so/help/webhooks.
Ostatni argument, czyli $payLoadBody to JSON, z tym co przychodzi w body webhook'a. przykład -> https://gist.github.com/smiell/3d31fa9208980c260d4bfe6a9f3a43b8

W logach otrzymuję przykładowo:

[28-Mar-2024 15:45:36 UTC] Hash coming from request: bcKrztQ1sO2maYAysLEag5k+M0rJ5cIyNauBXRq3F/c=
[28-Mar-2024 15:45:36 UTC] Hash saved in settings: 25b0285b-0187-4b1a-9ceb-af3d870a4a6134
[28-Mar-2024 15:45:36 UTC] Result of cryptographic count: YThjNTY4YjcwNGY4NjcyYmRkNWE4NTVmMDE3ZTM1YmRkYjM1NjU0ZjVkNmQxZTM0ODVhOTZlM2Q1ZTZmZDBhYQ==
[28-Mar-2024 15:45:36 UTC] Hash Invalid

Niestety nie otrzymuję Poprawnej kalkulacji. Postępowałem zgodnie z tym co Tally linkuje w swoich docsach: https://hookdeck.com/webhooks/guides/how-to-implement-sha256-webhook-signature-verification#php-example

Bardzo proszę o pomoc.

Tak wygląda wywołanie mojej metody IsWebhookTrusted:

            if ( !$this->IsWebhookTrusted( $encryption_key, $signature_header, $data['data'] ) ) {
                // Hash is not valid

                // Prepare response message
                $response_data = array(
                    'status' => 'error',
                    'response' => array(
                        'code' => 403,
                        'message' => 'Hash invalid. Bey, Bey...',
                    ),
                );
                return new WP_REST_Response( json_encode($response_data) , 403); // Return 403 Forbidden
            }

0

JSON.stringify z JS to nie do końca to samo co "gołe" json_encode z PHP ale myślę, że może pomóc dodanie odpowiednich parametrów https://www.php.net/manual/en/json.constants.php . Spróbuj:

$payLoadBodyString = json_encode($payLoadBody, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

edit// albo

$payLoadBodyString = json_encode($payLoadBody, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);

zależy co tam masz w tym body (w drugim przypadku liczby nie będą stringami w stylu "100" tylko zwyczajnie 100).

0

Body mojego $payLoadBody wygląda mniej więcej tak --> https://gist.github.com/smiell/3d31fa9208980c260d4bfe6a9f3a43b8

0

Sprawdziłem, dodałem to co zasugerowałeś, ale niestety dalej jest to samo... Hashę się nie zgadzają. Może w pierwszej kolejności należało by też hashować ten klucz, który mam w ustawieniach? W moim przypadku testowo: 25b0285b-0187-4b1a-9ceb-af3d870a4a6134

Hash przychodzący z przykładowego żądania: +iPmmVMYnJ7noyTHbgYgwaUFMHA+D9dcYgXEImTN9Mg=

1 użytkowników online, w tym zalogowanych: 0, gości: 1