# Vérifier l’authenticité d’un webhook Twilio avant de déclencher une réservation par SMS

> Un développeur intègre les notifications SMS entrantes de Twilio pour confirmer des réservations. Comment s'assurer que la requête reçue vient bien de Twilio.

- Auteur : Clément Hadrot
- Publié le : 2021-05-25
- Mis à jour le : 2021-05-25
- Catégorie : Sécurité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/securite/securiser-webhook-twilio-reservation-sms/

## L’essentiel

- Une URL de webhook devinée peut déclencher n'importe quelle action
- La signature X-Twilio-Signature valide l'origine de la requête
- Le rejeu d'une requête interceptée doit aussi être bloqué

`X-Twilio-Signature` : cet unique en-tête HTTP, présent sur chaque requête envoyée par Twilio vers un webhook, est ce qui sépare une notification SMS légitime d'une requête forgée par n'importe qui ayant deviné l'URL du point d'entrée. Un développeur travaillant sur un système de réservation par SMS pour un service de location de véhicules l'a découvert en creusant la documentation officielle, après avoir d'abord implémenté un webhook qui faisait confiance à tout ce qui lui arrivait.

Le principe du service : un client répond « OUI » à un SMS de confirmation pour valider sa réservation, ou envoie un mot-clé pour l'annuler. Twilio reçoit ces réponses et les retransmet vers une URL WordPress publique via une requête HTTP, qui déclenche alors la validation ou l'annulation côté base de données. L'envoi de SMS sortants, à l'origine des notifications, ne fait volontairement pas l'objet de cet article : le sujet ici est la réception, et la confiance qu'on peut accorder à une requête entrante.

## Le risque d'un webhook qui ne vérifie rien

Une URL de webhook, même complexe et difficile à deviner, finit toujours par être exposée d'une façon ou d'une autre : dans un journal serveur partagé par erreur, dans un outil de monitoring tiers, ou simplement par force brute sur un chemin prévisible comme `/wp-json/reservations/v1/sms-callback`. Sans vérification de l'origine, n'importe qui capable de deviner ou d'intercepter cette URL peut envoyer une requête qui imite un message Twilio et valider ou annuler des réservations à volonté, sans jamais passer par un vrai SMS.

## Vérifier la signature envoyée par Twilio

> L'essentiel à retenir : Une URL de webhook devinée peut déclencher n'importe quelle action ; La signature X-Twilio-Signature valide l'origine de la requête ; Le rejeu d'une requête interceptée doit aussi être bloqué

Twilio calcule un HMAC-SHA1 de l'URL complète du webhook, concaténée aux paramètres de la requête triés, signé avec le jeton d'authentification (auth token) propre au compte. Ce résultat est transmis dans l'en-tête `X-Twilio-Signature`. Le serveur recevant la requête doit refaire exactement le même calcul et comparer :

```
function verifier_signature_twilio( $url, $params, $signature_recue, $auth_token ) {
    ksort( $params );
    $donnees = $url;
    foreach ( $params as $cle => $valeur ) {
        $donnees .= $cle . $valeur;
    }
    $signature_calculee = base64_encode(
        hash_hmac( 'sha1', $donnees, $auth_token, true )
    );
    return hash_equals( $signature_calculee, $signature_recue );
}
```

L'usage de `hash_equals()` plutôt qu'une comparaison directe avec `==` ou `===` n'est pas cosmétique : il évite les attaques par mesure du temps de réponse (timing attacks), qui pourraient permettre de deviner une signature valide caractère par caractère.

### Ne jamais coder l'auth token en dur dans le fichier de traitement

Ce jeton, disponible dans la console Twilio, doit suivre les mêmes règles que tout secret sensible : lecture depuis une variable d'environnement, jamais versionné dans un dépôt Git, jamais affiché dans un journal de débogage.

## Se protéger du rejeu d'une requête interceptée

La signature garantit l'origine, pas la fraîcheur. Une requête valide, interceptée une première fois (par exemple sur un réseau mal sécurisé), pourrait en théorie être renvoyée telle quelle plus tard. Twilio inclut un identifiant unique de message (`MessageSid`) dans les paramètres transmis : conserver la liste des identifiants déjà traités, sur une fenêtre glissante de quelques heures, et rejeter tout doublon ferme cette porte.

## Répondre correctement pour éviter les répétitions automatiques

Twilio réessaie d'envoyer une notification si le webhook ne répond pas avec un code HTTP 200 dans un délai raisonnable. Un traitement trop lourd (écriture en base, envoi d'un email de confirmation, tout cela de façon synchrone) peut provoquer des retransmissions et donc des doublons de traitement. Répondre rapidement avec un code 200, puis traiter la logique métier via une tâche différée, évite ce piège.

> Un webhook qui déclenche une action métier réelle ne doit jamais se contenter de vérifier qu'une requête est arrivée : il doit vérifier qu'elle vient bien de qui elle prétend venir, et qu'elle n'a pas déjà été traitée.

## En résumé

La vérification de `X-Twilio-Signature` transforme un webhook ouvert à quiconque devine son URL en un point d'entrée fiable, à condition d'utiliser une comparaison sûre contre le rejeu temporel et de traiter séparément la déduplication par identifiant de message. Ces deux vérifications, une fois en place, retirent l'essentiel du risque lié à ce type d'intégration.
