I can't get GoCardless Webhook signature to match the computed signature

43 Views Asked by At

I am trying to match the GoCardless webhook supplied signature to the computed version that I generate in PHP. I'm using the following code but can't get $computed_signature to match $signature_header. Here's the code i'm using:

$webhook_endpoint_secret = getenv("Secret");
$request_body = file_get_contents('php://input');

$request_body_clean = preg_replace("/(\s{2,}|\t|\r|\n)/i",'',$request_body);

$headers = getallheaders();
$signature_header = $headers["Webhook-Signature"];

$payload = json_decode($request_body, true);

$computed_signature = hash_hmac("sha256", $request_body_clean, $webhook_endpoint_secret);

var_dump ($signature_header);
var_dump ($computed_signature);

I've tried without the preg_replace, in fact I don't think that does anything as they must send minified anyway. I've tried this the other way around like: $computed_signature = hash_hmac("sha256", $webhook_endpoint_secret, $request_body_clean); Gave a different signature (as it should) but still not correct.

Everything else is working fine, I can get the webhook info, I just can't seem to match signatures.

Am I doing something stupid here? Any help appreciated, many thanks.

2

There are 2 best solutions below

0
Chunks On

As I was in my test environment and using the GoCardless sandbox, I was placing the secret directly into the following:

$webhook_endpoint_secret = getenv("ugbo84d2rb7gcrbgcfpoiub9487gc74");

This didn't return anything (as it was looking for an environment variable), so the generated signature was wrong. I changed the test code to (fake secret for example):

$webhook_endpoint_secret = "ugbo84d2rb7gcrbgcfpoiub9487gc74";

and the signatures now match. This won't be set up like this in my production code, but just in case anyone else was testing as I was. It was just something silly.

0
yaroslawww On

GoCardless provide form library method what will do this job for you:

// We recommend storing your webhook endpoint secret in an environment variable
// for security
$webhook_endpoint_secret = getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET");
$request_body = file_get_contents('php://input');

$headers = getallheaders();
$signature_header = $headers["Webhook-Signature"];

try {
    $events = \GoCardlessPro\Webhook::parse($request_body,
                                            $signature_header,
                                            $webhook_endpoint_secret);

    // Process the events...

    header("HTTP/1.1 204 No Content");
} catch(\GoCardlessPro\Core\Exception\InvalidSignatureException $e) {
    header("HTTP/1.1 498 Invalid Token");
}