Skip to main content
Twenty possède deux familles de clés indépendantes :
  • Clés de signature JWT — paires de clés asymétriques ES256 (avec balise kid) stockées dans core."signingKey", utilisées pour signer et vérifier les jetons d’accès / de rafraîchissement.
  • Clé de chiffrement au reposENCRYPTION_KEY, utilisée pour chiffrer les jetons OAuth, les variables d’application, les clés privées de clés de signature, les valeurs de configuration sensibles et les secrets TOTP à l’intérieur d’une enveloppe enc:v2:.
APP_SECRET est un secret hérité conservé pour la rétrocompatibilité : lorsque ENCRYPTION_KEY n’est pas défini, il agit comme mécanisme de secours pour le chiffrement au repos / le cookie de session, et il continue de vérifier les jetons d’accès HS256 préexistants. Il sera déprécié.

Clés de signature JWT

Chaque clé contient une publicKey (conservée indéfiniment afin de pouvoir vérifier les jetons émis précédemment), une privateKey chiffrée (utilisée uniquement tant que la clé est actuelle), un indicateur isCurrent (exactement une ligne à la fois) et un champ revokedAt facultatif.

Faire pivoter la clé actuelle

Définissez SIGNING_KEY_ROTATION_DAYS pour l’activer : une tâche cron quotidienne émet alors une nouvelle clé actuelle dès que l’ancienne dépasse ce seuil. Les clés précédentes ne sont pas révoquées, donc les jetons signés avec celles-ci restent vérifiables. Laissez la variable non définie pour désactiver la rotation automatique.
La rotation automatique est disponible à partir de la v2.6+.

Révoquer une clé (fuite / urgence uniquement)

Settings → Admin Panel → Signing keys → Revoke sur une ligne non actuelle. Efface le matériel privé chiffré, définit revokedAt et rejette chaque jeton existant signé avec ce kid.

Faire pivoter ENCRYPTION_KEY

La commande secret-encryption:rotate décrite ci-dessous est fournie à partir de la v2.6+.
Chaque valeur chiffrée est encapsulée sous la forme enc:v2:\<keyId>:\<payload>, où \<keyId> est un préfixe hexadécimal sur 8 caractères dérivé de la clé brute. La rotation est en ligne et reprenable.
  1. Générez une nouvelle clé : openssl rand -base64 32.
  2. Configurez les deux clés côte à côte dans .env, puis redémarrez :
    ENCRYPTION_KEY=NEW_VALUE
    FALLBACK_ENCRYPTION_KEY=OLD_VALUE
    
    Les nouvelles écritures utilisent la nouvelle clé, les lignes existantes se déchiffrent toujours via la clé de secours.
  3. Rechiffrez les lignes existantes :
    docker exec -it {server_container} yarn command:prod secret-encryption:rotate
    
    La commande parcourt six sites (connected-account-tokens, application-variable, application-registration-variable, signing-key-private-keys, sensitive-config-storage, totp-secrets). Un filtre SQL ignore les lignes déjà sur le nouveau \<keyId>, de sorte que la commande est idempotente : interrompez-la et relancez-la si nécessaire. Quitte avec un code de sortie non nul si une ligne échoue — relancez pour réessayer.
    OptionDescription
    -s, --site \<site>Limiter à un seul site.
    -b, --batch-size \<n>Lignes par lot (valeur par défaut 200, maximum 5000).
    -d, --dry-runDéchiffrer + rechiffrer en mémoire, ignorer la commande UPDATE.
  4. Supprimez la clé de secours une fois que --dry-run n’affiche plus aucune ligne restante : supprimez FALLBACK_ENCRYPTION_KEY et redémarrez.

Prise en charge héritée de APP_SECRET

Les instances plus anciennes qui n’ont jamais défini ENCRYPTION_KEY utilisent APP_SECRET comme clé de chiffrement au repos (et comme secret de cookie de session, dérivé de celle-ci). Ce chemin est conservé pour la rétrocompatibilité mais est déprécié — définissez une ENCRYPTION_KEY dédiée et suivez la procédure de rotation ci-dessus pour migrer. APP_SECRET reste lui-même utilisé pour vérifier les anciens jetons d’accès HS256.