03-comment-je-travaille/guides/hsts.md

HSTS (HTTP Strict Transport Security)

HSTS force les navigateurs à utiliser HTTPS pour un domaine donné. Une fois actif, toute tentative en HTTP est automatiquement convertie en HTTPS par le navigateur, sans appel réseau en clair.

Comment ça fonctionne

  • Le serveur renvoie l'en-tĂȘte Strict-Transport-Security sur une rĂ©ponse HTTPS.
  • Le navigateur conserve cette rĂšgle pendant max-age secondes.
  • Tant que la rĂšgle est active, le navigateur refuse le HTTP.

Syntaxe de l'en-tĂȘte

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

ParamĂštres:

  • max-age: durĂ©e en secondes.
  • includeSubDomains: applique aussi aux sous-domaines.
  • preload: signal pour ĂȘtre Ă©ligible Ă  la liste de preload des navigateurs.

Pré-requis

  • HTTPS actif partout, certificat valide.
  • Redirection 301/308 de HTTP vers HTTPS.
  • Tous les sous-domaines doivent ĂȘtre compatibles HTTPS si includeSubDomains est activĂ©.

Recommandations

  • DĂ©marrer avec un max-age court (ex: 86400) puis augmenter.
  • Pour le preload: max-age >= 31536000 + includeSubDomains + preload.
  • Ne jamais envoyer HSTS sur un domaine qui sert encore du HTTP.

Implémentation Symfony

Option 1: niveau serveur (recommandé)

Nginx:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Apache:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Avantage: appliqué à toutes les réponses, y compris les fichiers statiques.

Option 2: niveau application (Symfony)

Ajoutez un subscriber qui pose l'en-tĂȘte uniquement en HTTPS.

// src/EventSubscriber/HstsSubscriber.php
namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

final class HstsSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::RESPONSE => 'onResponse'];
    }

    public function onResponse(ResponseEvent $event): void
    {
        $request = $event->getRequest();
        if (!$request->isSecure()) {
            return;
        }

        $event->getResponse()->headers->set(
            'Strict-Transport-Security',
            'max-age=31536000; includeSubDomains'
        );
    }
}

Notes:

  • Ne pas activer HSTS en dev local si vous n'utilisez pas HTTPS.
  • Si vous ĂȘtes derriĂšre un proxy, configurez trusted_proxies pour que isSecure() soit fiable.

Preload (optionnel)

Si vous voulez ĂȘtre prĂ©chargĂ©:

  1. Activer includeSubDomains et preload.
  2. Mettre max-age=31536000.
  3. Soumettre le domaine: https://hstspreload.org/

Checklist go/no-go (preload)

Go:

  • Tous les sous-domaines (existants et futurs) sont en HTTPS avec certificats valides.
  • Redirection 301/308 HTTP -> HTTPS en place partout.
  • Strict-Transport-Security envoyĂ© sur toutes les rĂ©ponses HTTPS.
  • max-age=31536000, includeSubDomains, preload dĂ©jĂ  en prod et testĂ©s.
  • Plan de rollback documentĂ© (retrait des directives + dĂ©lai de propagation).

No-go:

  • Un seul sous-domaine sert encore du HTTP ou est instable en HTTPS.
  • Certificats non gĂ©rĂ©s pour tous les sous-domaines.
  • Pas de visibilitĂ© sur tous les sous-domaines (legacy, marketing, vendors).
  • HSTS activĂ© rĂ©cemment sans pĂ©riode d'observation suffisante.
  • Redirections partielles ou incohĂ©rentes selon les apps/environnements.

Rollback (preload)

Si vous devez sortir du preload:

  1. Retirer preload de l'en-tĂȘte HSTS.
  2. Retirer includeSubDomains si tous les sous-domaines ne sont pas en HTTPS.
  3. Baisser max-age (ex: 0 ou trÚs court) pour limiter la durée restante.
  4. Attendre l'expiration cÎté clients (selon max-age).
  5. Soumettre la demande de retrait sur le site de preload (délai de propagation).

Note: le retrait est lent et dépend des mises à jour de listes intégrées aux navigateurs.

Vérification rapide

  • Outils dev navigateur: inspecter la rĂ©ponse HTTPS et l'en-tĂȘte HSTS.
  • OpenSSL/curl: curl -I https://votre-domaine.

Voir aussi — en production

Assistant documentaire

Posez une question sur la documentation. Les rĂ©ponses citent leurs sources — un clic ouvre le document Ă  gauche.

Loading…
Loading the web debug toolbar…
Attempt #