Skip to content

Latest commit

 

History

History
137 lines (99 loc) · 3.12 KB

verify-webhooks-from-nango.mdx

File metadata and controls

137 lines (99 loc) · 3.12 KB
title sidebarTitle description
Verify webhooks from Nango
Verify webhooks from Nango
Step-by-step guide on how to verify the signatures of webhooks from Nango.

Validate webhook provenance by looking at the X-Nango-Signature header.

It's a SHA-256 hash generated using the secret key found in the Environment Settings in the Nango UI.

The webhook signature can be generated with the following code:

async (req, res) => {
    const signature = req.headers['x-nango-signature'];
    const isValid = nango.verifyWebhookSignature(signature, req.body);
}
import crypto from 'crypto';

const secretKeyDev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
const signature = `${secretKeyDev}${JSON.stringify(payload)}`;
const hash = crypto.createHash('sha256').update(signature).digest('hex');
import hashlib
import json

secret_key_dev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
signature = f"{secret_key_dev}{json.dumps(payload)}"
hash = hashlib.sha256(signature.encode('utf-8')).hexdigest()
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;

public class Main {
    public static void main(String[] args) throws NoSuchAlgorithmException {
        String secretKeyDev = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
        String payloadString = // convert payload to JSON string
        String signature = secretKeyDev + payloadString;

        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = digest.digest(signature.getBytes("UTF-8"));
        String hash = DatatypeConverter.printHexBinary(hashBytes).toLowerCase();
    }
}
require 'json'
require 'digest'

secret_key_dev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
signature = "#{secret_key_dev}#{payload.to_json}"
hash = Digest::SHA256.hexdigest(signature)
package main

import (
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
)

func main() {
    secretKeyDev := "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    payloadString, _ := json.Marshal(payload) // Handle error in real code
    signature := secretKeyDev + string(payloadString)

    hash := sha256.Sum256([]byte(signature))
    hexHash := hex.EncodeToString(hash[:])
}
use sha2::{Sha256, Digest};
use serde_json::json; // Assuming use of serde_json for JSON serialization

let secret_key_dev = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
let signature = format!("{}{}", secret_key_dev, serde_json::to_string(&payload).unwrap());
let mut hasher = Sha256::new();
hasher.update(signature.as_bytes());
let hash = format!("{:x}", hasher.finalize());
<?php
$secretKeyDev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
$signature = $secretKeyDev . json_encode($payload);
$hash = hash('sha256', $signature);
?>

Only accept a webhook if the X-Nango-Signature header value matches the webhook signature.