PHP

Secure Webhook Signature Verification in PHP

Implement robust webhook signature verification in PHP to ensure the authenticity and integrity of incoming API payloads, protecting your application from forged requests.

<?php

/**
 * Verifies the signature of an incoming webhook payload.
 * This example assumes an HMAC-SHA256 signature provided in a header.
 *
 * @param string $payload The raw request body from the webhook.
 * @param string $secret The shared secret key provided by the webhook sender.
 * @param string $signatureHeader The value of the signature header (e.g., 'X-Hub-Signature-256').
 * @param string $algo The hashing algorithm to use (e.g., 'sha256', 'sha1').
 * @return bool True if the signature is valid, false otherwise.
 */
function verifyWebhookSignature(string $payload, string $secret, string $signatureHeader, string $algo = 'sha256'): bool
{
    // 1. Extract the expected signature from the header
    // Some services prefix with 'sha256=', others just provide the hash.
    // Adjust this parsing based on the specific service.
    if (strpos($signatureHeader, $algo . '=') === 0) {
        $expectedSignature = substr($signatureHeader, strlen($algo . '='));
    } else {
        $expectedSignature = $signatureHeader;
    }

    // 2. Compute the HMAC signature of the payload using the shared secret
    $computedSignature = hash_hmac($algo, $payload, $secret);

    // 3. Compare the computed signature with the expected signature
    // Use hash_equals() for constant-time comparison to prevent timing attacks.
    return hash_equals($expectedSignature, $computedSignature);
}

// --- Example Usage ---
// In a real scenario, $payload would come from file_get_contents('php://input')
// and $signatureHeader from $_SERVER or getallheaders().
// The secret should be securely stored (e.g., environment variable).

// $webhookSecret = getenv('WEBHOOK_SECRET') ?: 'your-very-secret-key';
// $receivedPayload = file_get_contents('php://input');
// $receivedSignatureHeader = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? ''; // Adjust header name

// if (verifyWebhookSignature($receivedPayload, $webhookSecret, $receivedSignatureHeader)) {
//     // Signature is valid, process the webhook data
//     $data = json_decode($receivedPayload, true);
//     // ... process data ...
//     http_response_code(200);
//     echo json_encode(['status' => 'success', 'message' => 'Webhook received and processed.']);
// } else {
//     // Signature is invalid, reject the request
//     error_log('Invalid webhook signature received!');
//     http_response_code(403); // Forbidden
//     echo json_encode(['status' => 'error', 'message' => 'Invalid signature.']);
// }

?>
How it works: This PHP snippet provides a function to securely verify webhook signatures. It takes the raw request body, a shared secret key, and the signature provided in the webhook header. It computes an HMAC signature of the payload using the secret and compares it against the received signature using `hash_equals()` to prevent timing attacks, ensuring the authenticity and integrity of webhook requests and protecting your application from forged data.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs