> ## Documentation Index
> Fetch the complete documentation index at: https://www.ayrshare.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rotation du secret de signature

> Effectuez une rotation sûre de votre secret de signature de webhook avec une fenêtre de grâce de double signature de 24 heures

export const PlansAvailable = ({plans = [], maxPackRequired}) => {
  let displayPlans = plans;
  if (plans && plans.length === 1) {
    const lowerCasePlan = plans[0].toLowerCase();
    if (lowerCasePlan === "business") {
      displayPlans = ["Launch", "Business", "Enterprise"];
    } else if (lowerCasePlan === "premium") {
      displayPlans = ["Premium", "Launch", "Business", "Enterprise"];
    }
  }
  return <Note>
Available on {displayPlans.length === 1 ? "the " : ""}
{displayPlans.join(", ").replace(/\b\w/g, l => l.toUpperCase())}{" "}
{displayPlans.length > 1 ? "plans" : "plan"}.

{maxPackRequired && <span onClick={() => window.open('https://www.ayrshare.com/docs/additional/maxpack', '_self')} className="flex items-center mt-2 cursor-pointer">
 <span className="px-1.5 py-0.5 rounded text-sm" style={{
    backgroundColor: '#C264B6',
    color: 'white',
    fontSize: '12px'
  }}>
   Max Pack required
 </span>
</span>}
</Note>;
};

export const HeaderAPI = ({noProfileKey, profileKeyRequired}) => <>
    <ParamField header="Authorization" type="string" required>
      <a href="/docs/apis/overview#authorization">API Key</a> of the Primary Profile.
      <br />
      <br />
      Format: <code>Authorization: Bearer API_KEY</code>
    </ParamField>
    {!noProfileKey && (profileKeyRequired ? <ParamField header="Profile-Key" type="string" required>
          <a href="/docs/apis/overview#profile-key-format">Profile Key</a> of a User Profile.
          <br />
          <br />
          Format: <code>Profile-Key: PROFILE_KEY</code>
        </ParamField> : <ParamField header="Profile-Key" type="string">
          <a href="/docs/apis/overview#profile-key-format">Profile Key</a> of a User Profile.
          <br />
          <br />
          Format: <code>Profile-Key: PROFILE_KEY</code>
        </ParamField>)}
  </>;

<PlansAvailable plans={["premium"]} maxPackRequired={false} />

## Vue d'ensemble

Ayrshare signe chaque livraison de webhook avec un [HMAC-SHA256](https://en.wikipedia.org/wiki/HMAC) de la charge utile, en utilisant votre **secret de signature** comme clé, afin que votre récepteur puisse confirmer qu'une livraison provient bien d'Ayrshare. Consultez [Sécurité des webhooks](/docs/apis/webhooks/overview#webhook-security) pour savoir comment fonctionne la vérification.

La rotation de votre secret de signature vous permet de le remplacer selon un calendrier régulier, ou immédiatement si vous soupçonnez qu'il a été exposé. Pour rendre la rotation sûre, Ayrshare ouvre une **fenêtre de grâce de 24 heures** après chaque rotation pendant laquelle les livraisons sont signées avec **à la fois** votre secret précédent et votre nouveau secret. Cela vous permet de mettre à jour votre récepteur à votre propre rythme sans manquer ou rejeter la moindre livraison — le même modèle que celui utilisé par Stripe et GitHub.

<Note>
  Le secret de signature est **à l'échelle du profil** : il y a un secret par User Profile (UID),
  et il signe **toutes** les actions de webhook que ce profil a enregistrées. Il n'existe pas
  de secret de signature par action — définir ou faire tourner le secret le modifie pour toutes
  les actions de ce profil en même temps.
</Note>

## Rotation depuis le tableau de bord

Vous pouvez définir ou faire tourner votre secret de signature depuis la [page Webhooks](https://app.ayrshare.com/webhooks) du tableau de bord développeur. Le panneau **Signing Secret** apparaît au-dessus de votre liste de webhooks une fois que le profil possède au moins un webhook enregistré.

<Steps>
  <Step title="Ouvrez le panneau Signing Secret">
    Rendez-vous sur la [page Webhooks](https://app.ayrshare.com/webhooks). Si aucun secret n'est encore configuré, le panneau affiche **No signing secret configured** avec un bouton **Set Signing Secret**. Si un secret est déjà configuré, il affiche **Signing secret configured** avec un bouton **Rotate**.
  </Step>

  <Step title="Définir ou effectuer la rotation">
    Cliquez sur **Set Signing Secret** (première fois) ou **Rotate** (secret existant). Une fenêtre modale s'ouvre avec un secret fort, généré aléatoirement, pré-rempli et révélé. Vous pouvez le **Copy**, en **Regenerate** un nouveau, ou basculer sur **paste my own** pour fournir votre propre valeur.
  </Step>

  <Step title="Confirmer">
    Copiez le secret dans un endroit sûr — il n'est affiché qu'une seule fois et ne peut plus jamais être récupéré depuis l'UI — puis confirmez pour soumettre. Un toast de succès apparaît et le panneau se met à jour.
  </Step>

  <Step title="Mettez à jour votre récepteur">
    Lors d'une rotation (et non d'une première définition), le panneau affiche un indicateur de fenêtre de grâce active et le bouton **Rotate** est désactivé jusqu'à la fermeture de la fenêtre. Vous disposez de 24 heures pour déployer le nouveau secret sur votre récepteur.
  </Step>
</Steps>

## Rotation via l'API

Effectuez la rotation (ou la définition) du secret de signature en un seul appel. Cela crée un nouveau secret, repointe la référence du secret du profil vers lui et — lorsqu'un secret existant était en place — enregistre le secret remplacé en tant que secret précédent avec une expiration dans 24 heures.

### Paramètres d'en-tête

<HeaderAPI />

### Paramètres du corps

<ParamField body="secret" type="string" required>
  La nouvelle valeur du secret de signature. Toute chaîne non vide est acceptée. Nous recommandons une valeur aléatoire longue et à haute entropie (par exemple, 32 octets aléatoires encodés en base64url).
</ParamField>

<RequestExample>
  ```bash cURL theme={"system"}
  curl --request POST \
    --url https://api.ayrshare.com/api/hook/webhook/secret \
    --header 'Authorization: Bearer YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --header 'Profile-Key: YOUR_PROFILE_KEY' \
    --data '{
      "secret": "your-new-signing-secret"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200: Response theme={"system"}
  {
    "status": "success",
    "action": "webhook",
    "refId": "3dc079614bdc3f281d9" // User Profile Ref Id
  }
  ```
</ResponseExample>

Le `secret` en clair n'est **jamais** renvoyé dans la réponse et n'est jamais enregistré dans les journaux. La réponse contient le `refId` destiné au client (un hachage de l'UID), jamais l'UID lui-même. L'en-tête `Profile-Key` est optionnel et limite la rotation à un seul User Profile pour les comptes multi-profils.

Un `secret` manquant ou vide renvoie une erreur mappée (`code: 101`, « Missing/incorrect parameter ») avec un statut HTTP `400`, et aucune modification n'est apportée à votre secret actuel. Une première définition via l'API (sans secret existant) crée le secret sans secret précédent enregistré et sans fenêtre de grâce.

## Procédure de rotation sûre

Grâce à la fenêtre de grâce de 24 heures, aucun ordre d'opérations n'est requis — votre récepteur continue de fonctionner pendant toute la durée. La séquence recommandée est la suivante :

<Steps>
  <Step title="Effectuez la rotation du secret">
    Effectuez la rotation depuis le tableau de bord ou via l'API. Ayrshare commence immédiatement à signer les livraisons avec à la fois votre secret précédent et votre nouveau secret.
  </Step>

  <Step title="Mettez à jour votre récepteur">
    Dans les 24 heures, déployez le nouveau secret sur votre récepteur de webhook afin qu'il vérifie par rapport à la nouvelle valeur.
  </Step>

  <Step title="Laissez la fenêtre se fermer">
    Après 24 heures, Ayrshare efface automatiquement le secret précédent et signe uniquement avec le nouveau secret. Aucune autre action n'est nécessaire de votre côté.
  </Step>
</Steps>

<Tip>
  Si vous effectuez une nouvelle rotation alors qu'une fenêtre de grâce est encore ouverte,
  le secret qui vient d'être remplacé devient le nouveau secret précédent et une nouvelle
  fenêtre de 24 heures démarre. Un seul secret précédent est conservé à la fois.
</Tip>

## Vérification des signatures pendant la fenêtre de grâce

En dehors d'une fenêtre de grâce, les livraisons signées portent les en-têtes standard (voir [Sécurité des webhooks](/docs/apis/webhooks/overview#webhook-security)) :

```bash theme={"system"}
X-Authorization-Timestamp : <Unix Timestamp In Seconds>
X-Authorization-Content-SHA256 : <current-sig>
X-Authorization-Content-SHA256-V2 : v1=<current-sig>
```

Pendant la fenêtre de 24 heures qui suit une rotation, le nouvel en-tête `X-Authorization-Content-SHA256-V2` liste **les deux** signatures, la signature actuelle en premier, séparées par une virgule :

```bash theme={"system"}
X-Authorization-Timestamp : <Unix Timestamp In Seconds>
X-Authorization-Content-SHA256 : <current-sig>
X-Authorization-Content-SHA256-V2 : v1=<current-sig>,v1=<previous-sig>
```

<Note>
  `X-Authorization-Content-SHA256` est inchangé : il porte toujours le HMAC unique
  du secret actuel, pour la rétrocompatibilité. Les doubles signatures n'apparaissent que
  dans le nouvel en-tête `X-Authorization-Content-SHA256-V2`.
</Note>

Chaque valeur dans `X-Authorization-Content-SHA256-V2` est préfixée par un tag de schéma. `v1=` désigne une signature HMAC-SHA256, calculée exactement comme `X-Authorization-Content-SHA256`. L'en-tête `-V2` est toujours présent lorsqu'une livraison est signée — il porte au moins `v1=<current-sig>` — vous pouvez donc vous y fier comme un contrat de récepteur stable.

Pour vérifier une livraison pendant (ou en dehors d')une rotation :

<Steps>
  <Step title="Calculez le HMAC">
    Calculez le HMAC-SHA256 du **corps de requête brut** en utilisant le secret de signature configuré localement.
  </Step>

  <Step title="Comparez à chaque signature listée">
    Lisez `X-Authorization-Content-SHA256-V2`, divisez-le sur les virgules, retirez le préfixe `v1=` de chaque valeur, et acceptez la livraison comme authentique si votre HMAC calculé correspond à **n'importe quelle** signature `v1=` listée.
  </Step>
</Steps>

Accepter si **n'importe quelle** signature listée correspond est ce qui rend la rotation sans interruption : un récepteur toujours configuré avec l'ancien secret correspond à `v1=<previous-sig>`, tandis qu'un récepteur mis à jour vers le nouveau secret correspond à `v1=<current-sig>` — les deux réussissent pendant toute la durée de la fenêtre.

### Exemple de vérification côté récepteur

```javascript Node.js theme={"system"}
import crypto from "crypto";

// secret is the signing secret currently configured on your receiver.
function isAuthenticWebhook(rawBody, headers, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody) // the raw, unparsed request body
    .digest("hex");

  const headerValue = headers["x-authorization-content-sha256-v2"] || "";

  // Accept if ANY v1= signature in the header matches our computed HMAC.
  return headerValue
    .split(",")
    .map((part) => part.trim())
    .filter((part) => part.startsWith("v1="))
    .map((part) => part.slice("v1=".length))
    .some((sig) => {
      const sigBuf = Buffer.from(sig);
      const expectedBuf = Buffer.from(expected);
      // timingSafeEqual throws on length mismatch — treat as not authentic.
      return (
        sigBuf.length === expectedBuf.length &&
        crypto.timingSafeEqual(sigBuf, expectedBuf)
      );
    });
}
```

<Warning>
  Calculez toujours le HMAC sur les **octets bruts** du corps de la requête, exactement tels que
  reçus — et non sur un objet JSON re-sérialisé. La re-sérialisation peut modifier
  les espaces ou l'ordre des clés et rompre la vérification. Utilisez une comparaison à temps constant
  (telle que `crypto.timingSafeEqual`) pour éviter les attaques temporelles.
</Warning>

Si l'enregistrement du secret actuel d'une livraison est manquant, la livraison se poursuit **sans signature** (aucun en-tête de signature) plutôt que d'échouer. Si seul l'enregistrement du secret précédent est absent, la signature précédente est ignorée et la signature actuelle est toujours émise dans les deux en-têtes.
