Comment vérifier les signatures de webhook Zendesk : Un guide complet pour les développeurs

Stevia Putri
Written by

Stevia Putri

Reviewed by

Stanley Nicholas

Last edited 2 mars 2026

Expert Verified

Image de bannière pour Comment vérifier les signatures de webhook Zendesk : Un guide complet pour les développeurs

Lorsque vous créez des intégrations qui reçoivent des webhooks de Zendesk, vous ouvrez un point de terminaison sur votre serveur qui accepte les requêtes HTTP provenant d’Internet. Sans vérification appropriée, n’importe qui pourrait envoyer de fausses requêtes à ce point de terminaison et potentiellement déclencher des actions indésirables dans votre système. C’est là que la vérification de la signature entre en jeu.

La vérification de la signature du webhook Zendesk vous offre un moyen de prouver cryptographiquement que les webhooks entrants proviennent réellement de Zendesk et n’ont pas été altérés en transit. Ce guide vous explique tout ce dont vous avez besoin pour l’implémenter correctement, avec des exemples de code fonctionnels dans cinq langages de programmation populaires.

Si vous recherchez des conseils plus généraux sur la configuration des webhooks dans Zendesk, notre guide de configuration des webhooks de messagerie Zendesk couvre l’ensemble du processus de configuration.

Tableau de bord de simulation eesel AI montrant les taux d’automatisation prédits pour une intégration Zendesk ChatGPT
Tableau de bord de simulation eesel AI montrant les taux d’automatisation prédits pour une intégration Zendesk ChatGPT

Qu’est-ce que la vérification de la signature du webhook et pourquoi est-ce important ?

La vérification de la signature du webhook est un mécanisme de sécurité qui vous permet de confirmer l’authenticité des requêtes de webhook entrantes. Lorsque Zendesk envoie un webhook à votre point de terminaison, il inclut une signature cryptographique que seul Zendesk aurait pu générer. Votre serveur recalcule cette signature à l’aide d’un secret partagé et compare les résultats. S’ils correspondent, le webhook est authentique.

Sans cette vérification, votre point de terminaison est vulnérable à plusieurs attaques :

  • Usurpation : Quiconque découvre l’URL de votre webhook pourrait envoyer de fausses requêtes en se faisant passer pour Zendesk
  • Attaques de relecture : Un attaquant pourrait capturer un webhook légitime et le renvoyer plusieurs fois
  • Altération de la charge utile : Les données de requête pourraient être modifiées en transit sans être détectées

Pour les intégrations de production qui traitent des données de ticket sensibles ou qui déclenchent des flux de travail automatisés, la vérification de la signature n’est pas facultative. Il s’agit d’un contrôle de sécurité fondamental qui protège à la fois votre système et les données de vos clients.

Chez eesel AI, nous gérons automatiquement la sécurité des webhooks lorsque vous connectez votre compte Zendesk. Notre plateforme vérifie les signatures de manière transparente afin que vous puissiez vous concentrer sur la création d’automatisations plutôt que sur les implémentations cryptographiques.

Comment fonctionnent les signatures de webhook Zendesk

Zendesk utilise l’algorithme SHA256 HMAC (Hash-based Message Authentication Code, code d’authentification de message basé sur le hachage) pour générer des signatures de webhook. Le processus combine le secret de signature de votre webhook avec la charge utile de la requête et l’horodatage pour créer une signature unique pour chaque requête.

La formule ressemble à ceci :

base64(HMACSHA256(TIMESTAMP + BODY))

Voici ce qui se passe lorsque Zendesk envoie un webhook :

  1. Zendesk concatène l’horodatage et le corps de la requête brute en une seule chaîne
  2. Il crée un hachage HMAC-SHA256 à l’aide du secret de signature de votre webhook comme clé
  3. Le hachage est codé en Base64 pour produire la signature finale
  4. Zendesk envoie le webhook avec deux en-têtes essentiels :
    • X-Zendesk-Webhook-Signature : la signature générée
    • X-Zendesk-Webhook-Signature-Timestamp : l’horodatage utilisé dans la signature

Chaque requête de webhook de Zendesk inclut ces en-têtes standard :

x-zendesk-account-id: 123456
x-zendesk-webhook-id: 01F1KRFQ6BG29CNWFR60NK5FNY
x-zendesk-webhook-invocation-id: 8350205582
x-zendesk-webhook-signature: EiqWE3SXTPQpPulBV6OSuuGziIishZNc1VwNZYqZrHU=
x-zendesk-webhook-signature-timestamp: 2021-03-25T05:09:27Z

Sur votre serveur, vous extrayez ces en-têtes, recalculez la signature à l’aide de votre secret de signature stocké et comparez les résultats. Si les signatures correspondent, vous pouvez être sûr que le webhook provient de Zendesk et que la charge utile n’a pas été modifiée.

Flux de vérification de la signature du webhook de Zendesk vers votre serveur
Flux de vérification de la signature du webhook de Zendesk vers votre serveur

Récupération de votre secret de signature de webhook

Avant de pouvoir vérifier les signatures, vous avez besoin du secret de signature de votre webhook. Chaque webhook dans Zendesk possède son propre secret unique qui est généré lors de la création du webhook.

Trouver votre secret dans le Centre d’administration

  1. Accédez au Centre d’administration Zendesk (Centre d’administration > Applications et intégrations > Webhooks)
  2. Sélectionnez le webhook que vous souhaitez vérifier
  3. Sur la page des détails du webhook, recherchez le champ du secret de signature
  4. Cliquez sur « Révéler le secret » pour afficher la valeur

Interface de configuration du webhook Zendesk montrant les méthodes de connexion
Interface de configuration du webhook Zendesk montrant les méthodes de connexion

Traitez ce secret comme n’importe quel autre identifiant. Ne l’intégrez pas au code, ne l’exposez pas dans les applications côté client et limitez-en l’accès au sein de votre équipe.

Récupération via l’API

Vous pouvez également récupérer le secret de signature par programmation à l’aide de l’API Afficher le secret de signature du webhook :

GET /api/v2/webhooks/{webhook_id}/signing_secret

Secret de test statique pour le développement

Lorsque vous testez des webhooks avant de les créer dans Zendesk, vous aurez besoin d’un secret de signature statique, car les secrets réels ne sont générés qu’après la création du webhook. Utilisez ce secret de test pendant le développement :

dGhpc19zZWNyZXRfaXNfZm9yX3Rlc3Rpbmdfb25seQ==

Une fois votre webhook créé, passez au secret de signature réel. Les webhooks de test et les webhooks en direct utilisent des secrets différents, votre code de vérification doit donc gérer le secret correct pour chaque environnement.

Capture d’écran de la page de destination Zendesk
Capture d’écran de la page de destination Zendesk

Guide d’implémentation étape par étape

L’implémentation de la vérification de la signature implique quatre étapes clés. Décomposons chacune d’elles.

Étape 1 : Capturez le corps de la requête brute

La signature est calculée sur le corps de la requête brute sous forme de chaîne, et non sur les données JSON ou de formulaire analysées. Si votre framework analyse le corps avant que vous puissiez y accéder, la vérification de la signature échouera car les octets bruts ont été transformés.

La plupart des frameworks Web fournissent des options de middleware ou de configuration pour capturer le corps brut avant l’analyse. Vous devez généralement stocker le corps brut dans une propriété telle que req.rawBody afin qu’il soit disponible pour le calcul de la signature.

Piège courant : Le middleware d’analyse du corps (comme express.json() d’Express) s’exécute souvent avant votre gestionnaire de route. Si le corps est analysé en un objet JavaScript avant que vous ne capturiez la chaîne brute, vous ne pouvez pas récupérer les octets d’origine pour la vérification de la signature. Configurez votre middleware pour capturer d’abord le corps brut.

Étape 2 : Extrayez les en-têtes de signature

Extrayez les deux en-têtes liés à la signature de la requête entrante :

  • X-Zendesk-Webhook-Signature : la signature à vérifier
  • X-Zendesk-Webhook-Signature-Timestamp : l’horodatage utilisé dans le calcul de la signature

Notez que certains frameworks transforment les noms d’en-tête. Dans Ruby on Rails, par exemple, l’en-tête X-Zendesk-Webhook-Signature devient HTTP_X_ZENDESK_WEBHOOK_SIGNATURE dans l’environnement de requête.

Étape 3 : Calculez la signature attendue

Concaténez l’horodatage et le corps brut, puis créez un hachage HMAC-SHA256 à l’aide de votre secret de signature :

  1. Créez une chaîne : timestamp + body (horodatage d’abord, puis le corps brut)
  2. Générez HMAC-SHA256 à l’aide de votre secret de signature comme clé
  3. Encodez le hachage résultant en Base64

Cette signature calculée doit correspondre à celle que Zendesk a envoyée dans l’en-tête X-Zendesk-Webhook-Signature.

Étape 4 : Comparez les signatures en toute sécurité

Utilisez une fonction de comparaison à temps constant pour comparer les signatures. La comparaison de chaînes régulière (== ou ===) peut divulguer des informations sur la signature par le biais d’une analyse temporelle, ce qui pourrait théoriquement aider un attaquant à forger des signatures valides.

La plupart des langages fournissent une fonction de comparaison à temps constant :

  • Node.js : crypto.timingSafeEqual()
  • Python : hmac.compare_digest()
  • PHP : hash_equals()
  • Ruby : ActiveSupport::SecurityUtils.secure_compare()
  • C# : Pas de comparaison à temps constant intégrée, mais CryptographicOperations.FixedTimeEquals() dans .NET Core

Si les signatures correspondent, traitez le webhook. Si elles ne correspondent pas, renvoyez une réponse 401 Non autorisé et enregistrez l’échec pour enquête.

Exemples de code dans les langages populaires

Voici des implémentations complètes et fonctionnelles pour les langages de développement Web les plus courants.

Node.js/Express

const express = require('express');
const crypto = require('crypto');

const SIGNING_SECRET = 'your_webhook_signing_secret_here';
const PORT = 3000;
const app = express();

// Middleware to capture raw body
function storeRawBody(req, res, buf) {
  if (buf && buf.length) {
    req.rawBody = buf.toString('utf8');
  }
}

app.use(express.json({ verify: storeRawBody }));
app.use(express.urlencoded({ verify: storeRawBody, extended: true }));

function isValidSignature(signature, body, timestamp) {
  const hmac = crypto.createHmac('sha256', SIGNING_SECRET);
  const sig = hmac.update(timestamp + body).digest('base64');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(sig)
  );
}

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-zendesk-webhook-signature'];
  const timestamp = req.headers['x-zendesk-webhook-signature-timestamp'];
  const body = req.rawBody;

  if (!isValidSignature(signature, body, timestamp)) {
    console.log('Invalid webhook signature');
    return res.status(401).send('Unauthorized');
  }

  // Process the verified webhook
  console.log('Webhook verified, processing...');
  res.status(200).send('OK');
});

app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Python (Flask)

from flask import Flask, request, abort
import hmac
import hashlib
import base64

app = Flask(__name__)
SIGNING_SECRET = b'your_webhook_signing_secret_here'

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    # Get raw body
    raw_body = request.get_data()

    # Extract headers
    signature = request.headers.get('X-Zendesk-Webhook-Signature', '')
    timestamp = request.headers.get('X-Zendesk-Webhook-Signature-Timestamp', '')

    # Calculate expected signature
    signed_payload = (timestamp + raw_body.decode('utf-8')).encode('utf-8')
    expected_signature = base64.b64encode(
        hmac.new(SIGNING_SECRET, signed_payload, hashlib.sha256).digest()
    ).decode('utf-8')

    # Verify signature
    if not hmac.compare_digest(expected_signature, signature):
        abort(401)

    # Process verified webhook
    return '', 200

if __name__ == '__main__':
    app.run(port=3000)

PHP

<?php

define('SIGNING_SECRET', 'your_webhook_signing_secret_here');

function verify_webhook($body, $signature, $timestamp) {
    // Concatenate timestamp and body
    $signed_payload = $timestamp . $body;

    // Calculate HMAC (binary output)
    $calculated_hmac = base64_encode(
        hash_hmac('sha256', $signed_payload, SIGNING_SECRET, true)
    );

    // Constant-time comparison
    return hash_equals($signature, $calculated_hmac);
}

// Handle webhook request
$signature = $_SERVER['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE_TIMESTAMP'] ?? '';
$body = file_get_contents('php://input');

if (!verify_webhook($body, $signature, $timestamp)) {
    http_response_code(401);
    exit('Unauthorized');
}

// Process verified webhook
http_response_code(200);
echo 'OK';

Ruby on Rails

class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  SIGNING_SECRET = ENV['ZENDESK_WEBHOOK_SECRET']

  def zendesk
    signature = request.headers['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE']
    timestamp = request.headers['HTTP_X_ZENDESK_WEBHOOK_SIGNATURE_TIMESTAMP']
    body = request.body.read

    # Calculate signature
    signed_payload = timestamp + body
    expected_signature = Base64.strict_encode64(
      OpenSSL::HMAC.digest('SHA256', SIGNING_SECRET, signed_payload)
    )

    # Verify
    unless ActiveSupport::SecurityUtils.secure_compare(expected_signature, signature)
      head :unauthorized
      return
    end

    # Process webhook
    head :ok
  end
end

C#

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("webhook")]
public class WebhookController : ControllerBase
{
    private const string SigningSecret = "your_webhook_signing_secret_here";

    [HttpPost]
    public IActionResult HandleWebhook()
    {
        string signature = Request.Headers["X-Zendesk-Webhook-Signature"];
        string timestamp = Request.Headers["X-Zendesk-Webhook-Signature-Timestamp"];

        // Read raw body
        using var reader = new StreamReader(Request.Body);
        string body = reader.ReadToEnd();

        // Calculate signature
        string signedPayload = timestamp + body;
        byte[] keyBytes = Encoding.UTF8.GetBytes(SigningSecret);
        byte[] payloadBytes = Encoding.UTF8.GetBytes(signedPayload);

        using var hmac = new HMACSHA256(keyBytes);
        byte[] hash = hmac.ComputeHash(payloadBytes);
        string expectedSignature = Convert.ToBase64String(hash);

        // Compare (case-insensitive for compatibility)
        if (!signature.Equals(expectedSignature, StringComparison.OrdinalIgnoreCase))
        {
            return Unauthorized();
        }

        return Ok();
    }
}

Problèmes courants et dépannage

Même avec le bon code, la vérification de la signature peut échouer pour des raisons subtiles. Voici les problèmes les plus courants que rencontrent les développeurs.

Espacement et formatage JSON

L’un des problèmes les plus frustrants concerne le formatage JSON. La signature est calculée sur les octets exacts que Zendesk envoie, y compris les espaces blancs. Si votre framework reformate le JSON (en ajoutant ou en supprimant des espaces), la signature ne correspondra pas.

Un développeur de la communauté Zendesk l’a découvert à ses dépens :

Communauté Zendesk
Je l’ai compris. C’était lié à l’espacement de la requête json. La charge utile json doit avoir un espace avant et après « : » et aucun autre espace ou onglet ailleurs.

La solution consiste à toujours vérifier la signature par rapport au corps de la requête brute avant toute analyse ou transformation.

Différences entre le webhook de test et le webhook en direct

Un autre problème courant concerne les différences entre la fonctionnalité de webhook de test de Zendesk et les appels de webhook en direct. Le format de la charge utile peut varier légèrement entre les deux, ce qui entraîne la validation des signatures lors des tests, mais l’échec en production.

Communauté Zendesk
J’ai remarqué que lorsque le webhook s’exécute normalement, l’authentification du message échoue. J’ai donc copié le corps de la tentative infructueuse, je suis retourné à « Tester le webhook », j’ai collé le contenu dans le corps du message, je l’ai envoyé et la validation du message fonctionne à nouveau.

Testez toujours avec des appels de webhook réels à partir d’événements Zendesk réels avant de déployer en production.

Encodage des caractères

Assurez-vous que l’horodatage et le corps sont gérés comme des chaînes UTF-8 lors de la concaténation pour le calcul de la signature. Les incompatibilités d’encodage entre votre serveur et la charge utile de Zendesk entraîneront des échecs de vérification.

Validation de l’horodatage

Envisagez d’ajouter une validation d’horodatage pour empêcher les attaques de relecture. Vérifiez que l’horodatage dans l’en-tête se trouve dans une fenêtre raisonnable (par exemple, 5 minutes) de l’heure actuelle. Les anciens horodatages pourraient indiquer une attaque de relecture.

Quand régénérer les secrets

Si vous soupçonnez que votre secret de signature a été compromis, régénérez-le immédiatement via le Centre d’administration Zendesk. Après la régénération, mettez à jour votre serveur avec le nouveau secret. Il peut y avoir une brève fenêtre où les webhooks en vol utilisent l’ancien secret, alors envisagez de prendre en charge les deux pendant la transition.

Tester votre vérification de webhook

Avant de déployer en production, testez minutieusement votre implémentation de vérification de la signature.

Utilisation du secret de test statique

Pendant le développement, utilisez le secret de test statique de Zendesk (dGhpc19zZWNyZXRfaXNfZm9yX3Rlc3Rpbmdfb25seQ==) pour vérifier que votre logique d’implémentation est correcte. Cela vous permet de tester sans créer de webhook en direct.

Test avec la fonctionnalité de test de Zendesk

Lorsque vous créez ou modifiez un webhook dans Zendesk, utilisez le bouton « Tester le webhook » pour envoyer des charges utiles de test. Vérifiez que votre point de terminaison accepte ces requêtes et valide correctement la signature.

Tests en direct

Créez un déclencheur réel qui appelle votre webhook sur un événement spécifique (comme la création d’un ticket). Effectuez cette action dans Zendesk et confirmez que votre point de terminaison reçoit et vérifie le webhook. Vérifiez vos journaux de serveur pour toute incompatibilité de signature.

Journalisation et débogage

Consignez les informations suivantes pendant le développement pour faciliter le débogage des échecs :

  • Corps de la requête brute (avant l’analyse)
  • En-tête de signature reçu
  • Signature calculée
  • En-tête d’horodatage

Ne consignez jamais le secret de signature lui-même. Comparez les signatures reçues et calculées caractère par caractère pour identifier où elles divergent.

Flux de travail de test systématique pour la vérification de la signature du webhook
Flux de travail de test systématique pour la vérification de la signature du webhook

Sécurisez vos intégrations Zendesk avec eesel AI

L’implémentation correcte de la vérification de la signature du webhook nécessite une attention particulière aux détails cryptographiques, à la gestion du corps spécifique au framework et aux cas extrêmes concernant le formatage JSON. Pour les équipes qui créent des intégrations complexes, cette complexité peut ralentir le développement et introduire des risques de sécurité.

Chez eesel AI, nous avons intégré la sécurité des webhooks directement dans notre intégration Zendesk. Lorsque vous connectez votre compte Zendesk à notre plateforme, nous gérons automatiquement la vérification de la signature. Vous bénéficiez des avantages de la sécurité sans écrire ni maintenir de code de vérification.

Tableau de bord eesel AI pour la configuration de l’agent superviseur avec une interface sans code
Tableau de bord eesel AI pour la configuration de l’agent superviseur avec une interface sans code

Notre agent d’IA pour Zendesk va plus loin, en fournissant une résolution autonome des tickets tout en gérant toute la sécurité des webhooks en arrière-plan. Si vous créez des automatisations basées sur des webhooks et que vous souhaitez vous concentrer sur la logique métier plutôt que sur les implémentations cryptographiques, nous pouvons vous aider à simplifier votre intégration.

Foire aux questions

Oui, vous avez besoin d’un accès administrateur au Centre d’administration Zendesk pour afficher ou régénérer les secrets de signature de webhook. Les secrets sont masqués par défaut et nécessitent de cliquer sur « Révéler le secret » pour s’afficher.
Non, chaque webhook possède son propre secret de signature unique généré lors de sa création. Vous ne pouvez pas partager de secrets entre les webhooks, et toute tentative de vérification de la charge utile d’un webhook avec le secret d’un autre webhook échouera toujours.
Tout d’abord, vérifiez que vous utilisez le secret de signature correct (pas le secret de test statique pour les webhooks en direct). Vérifiez que vous capturez le corps de la requête brute avant toute analyse JSON. Assurez-vous que votre concaténation d’horodatage et de corps correspond exactement au format de Zendesk. Enfin, vérifiez qu’il n’y a pas de problèmes d’encodage avec la charge utile.
Bien que cela ne soit pas strictement requis, la vérification de la signature est fortement recommandée pour toute intégration de production. Sans cela, votre point de terminaison est vulnérable à l’usurpation et aux attaques de relecture. Zendesk inclut les en-têtes de signature sur tous les webhooks, il n’y a donc aucun inconvénient à les vérifier.
Faites pivoter vos secrets de signature chaque fois que vous soupçonnez une compromission, lorsque des membres de l’équipe ayant accès partent, ou dans le cadre d’un audit de sécurité régulier (trimestriellement ou annuellement). N’oubliez pas que la rotation d’un secret nécessite la mise à jour immédiate de votre code de vérification, car les nouveaux webhooks utiliseront le nouveau secret.
Non, le secret de test statique ne fonctionne qu’avec la fonctionnalité « Tester le webhook » de Zendesk lors de la création du webhook. Une fois qu’un webhook est créé, il obtient son propre secret de signature unique que vous devez utiliser pour la vérification.
Tout langage qui prend en charge le hachage HMAC-SHA256 et le codage Base64 peut vérifier les webhooks Zendesk. Les implémentations les plus courantes utilisent Node.js, Python, PHP, Ruby, Java, C# et Go. Les opérations cryptographiques sont standard et disponibles dans la plupart des bibliothèques standard de langage.

Partager cet article

Stevia undefined

Article by

Stevia Putri

Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.