ADR-0005

Format des tokens de session : Paseto v4 public

source : docs/adr/0005-token-format-paseto-v4.md · versionné · MADR-lite

ADR-0005 — Format des tokens de session : Paseto v4 public

  • Statut : Accepted
  • Date : 2026-04-24
  • Décideurs : Core team OmbrysWeb
  • Issue GitHub : #25
  • Références : cahier des charges § 5.1, § 6.1 ; ADR-0002 (crypto strategy)
  • Dépend de : ADR-0001, ADR-0002

Contexte

Après authentification WebAuthn réussie (cf. ADR-0002, issue #23), auth-svc émet un token porté par le frontend pour les requêtes subséquentes vers les autres micro-services. Ce token est le support de la session applicative courte (15 min, cf. crypto-spec § 4.1), avec :

  • iss, sub, iat, nbf, exp standards,
  • sid identifiant unique de session,
  • did identifiant device / Passkey utilisé,
  • assurance niveau (base après login normal, stepup après re-auth biométrique).

Deux formats sérieux étaient en lice : JWT EdDSA (EdDSA sur courbe Ed25519, RFC 8037) et Paseto v4 public.

Options

JWT (RFC 7519) avec EdDSA

Pour : - Format standard largement déployé, librairies partout. - Claims flexibles, extensible sans perte de compatibilité. - EdDSA est sûre et rapide (Ed25519).

Contre : - Le header embarque alg, ce qui historiquement a permis des attaques : - alg: none (libs bogguées), - confusion RS256/HS256 (clé publique interprétée comme clé symétrique), - confusion RSA/EC. - Même quand la lib valide strictement, le mécanisme même de choix d'algo est un poids cognitif et une source de CVE récurrentes. - Pas de cryptographic binding entre le header typ et le reste. Une implémentation laxiste peut accepter un token "ressemblant".

Paseto v4 public (version 4, purpose public)

Pour : - Pas de négociation d'algorithme. Le purpose v4.public fixe Ed25519 exclusivement. Aucun header modifiable par l'attaquant. - Le préfixe de version/purpose (v4.public.) est authentifié et vérifié avant toute interprétation des claims. - Les "footer" et "implicit assertion" (IA) permettent de bind des métadonnées publiques (ex : version du schema de claims) à la signature, sans les chiffrer. - Spécifiquement conçu par des spécialistes pour éviter les erreurs JWT. - Signatures Ed25519, même perf que JWT EdDSA.

Contre : - Moins de librairies (en Rust : rusty_paseto mature mais unique acteur sérieux). - Adoption moins large que JWT → un intégrateur tiers peut ne pas connaître. - Évolution du format demande un bump de version (déjà bump 1→2→3→4).

Décision

Paseto v4 public pour les tokens de session utilisateur.

  • Implémentation Rust via rusty_paseto (prelude haut niveau côté serveur ; le frontend Next.js vérifie uniquement via appel à auth-svc — il ne décode jamais lui-même, donc pas de lib Paseto côté navigateur).
  • Seed Ed25519 32 octets stocké dans Vault (kv/services/auth-svc/token-seed), rotation tous les 30 jours ou sur incident.
  • Clé publique distribuée aux autres micro-services via SPIFFE workload identity + endpoint interne auth-svc:/v1/keys/current + /v1/keys/previous (pour supporter la rotation).
  • Claims portés définis dans ombrys_tokens::SessionClaims.
  • Footer v1 portant {"kid": "seed-<epoch>"} pour router la vérification vers la bonne clé pendant une rotation.

Conséquences

Positives

  • Surface d'attaque très réduite comparée à JWT — zéro ambiguïté d'algorithme.
  • Zero allocation côté lib, perf excellente.
  • Claims standards préservés → migration future vers JWT (si nécessaire) triviale.
  • Le déploiement s'appuie déjà sur Ed25519 pour le journal d'audit et pour SPIFFE SVID JWT.

Négatives

  • Pas de lib Paseto mainstream côté iOS/Android natif (problème pour le client mobile v2). Mitigation : wrapper Rust via UniFFI quand on attaquera le mobile.
  • Écosystème plus petit → revue sécurité plus cruciale sur la lib.

Neutres

  • Les tokens PASETO commencent par v4.public. — facilement reconnaissables dans les logs, ce qui aide à la détection de fuites (règles gitleaks custom).

Suivi

  • Rotation du seed : procédure documentée dans docs/operations/key-rotation.md (à rédiger en M2).
  • Revue sécurité : audit externe M6 couvre explicitement la chaîne de tokens.
  • Évolution : si Paseto ajoute v5 avec PQ natif, ADR de révision. Pour l'instant les tokens courts ne nécessitent pas de PQ (menace « harvest now, decrypt later » négligeable sur des tokens de 15 min).

Changelog

  • 2026-04-24 : rédaction initiale, statut Accepted.