anchorage_layer_simple/features/service-login-verify.md
ncantu 6bf37be44e Cron restart services (bitcoind, mempool), service-login-verify, website-skeleton, docs
**Motivations:**
- Consigner l'état actuel du dépôt (cron, service-login-verify, website-skeleton, userwallet, docs).
- Centraliser les modifications en attente.

**Root causes:**
- N/A (commit groupé).

**Correctifs:**
- N/A.

**Evolutions:**
- Cron quotidien restart services : script local sans SSH, systemd (bitcoin-signet, bitcoin, APIs, dashboard, userwallet, website-skeleton) + Docker (mempool, bitcoin-signet-instance).
- Feature cron-restart-services-local : documentation et règle scripts locaux / pas d'SSH.
- service-login-verify : module vérification login (buildAllowedPubkeys, verifyLoginProof, nonceCache).
- website-skeleton : app iframe UserWallet, config, systemd unit.
- userwallet : collectSignatures, relay.
- docs : DOMAINS_AND_PORTS, README, WEBSITE_SKELETON ; features userwallet-contrat-login, timeouts-backoff, service-login-verify.

**Pages affectées:**
- data/restart-services-cron.sh, data/restart-services.log, data/sync-utxos.log
- features/cron-restart-services-local.md, features/service-login-verify.md, features/userwallet-contrat-login-reste-a-faire.md, features/userwallet-timeouts-backoff.md
- docs/DOMAINS_AND_PORTS.md, docs/README.md, docs/WEBSITE_SKELETON.md
- configure-nginx-proxy.sh
- service-login-verify/ (src, dist, node_modules)
- userwallet/src/utils/collectSignatures.ts, userwallet/src/utils/relay.ts
- website-skeleton/
2026-01-28 00:48:37 +01:00

4.6 KiB
Raw Blame History

Côté service Acceptation de session et politique anti-rejeu (3.7)

Author: Équipe 4NK
Date: 2026-01-26

Explication

Rôle du « service »

Le service est lapplication parente qui embarque UserWallet en iframe. Cest elle qui consomme le login : elle reçoit la preuve de login (login-proof) via postMessage, doit laccepter ou refuser pour ouvrir une session, sans serveur central.

  • UserWallet (iframe) envoie { type: 'login-proof', payload: LoginProof } au parent.
  • Le parent écoute window.addEventListener('message', ...), filtre event.data?.type === 'login-proof', puis vérifie la preuve avant daccepter la session.

Acceptation de session

Le service doit vérifier la preuve en sappuyant uniquement sur contrats + signatures :

  1. Graphe contractuel : le service dispose du contrat (et contrats fils) du service, fourni par channel message ou contrat par défaut. Il peut en déduire laction login, les membres, les validateurs.
  2. Clés autorisées : à partir des validateurs de laction login (membres_du_role[].signatures_obligatoires[].cle_publique), construire lensemble des cle_publique autorisées à signer. (Résolution pair_uuid → clé non utilisée côté service si seules les cle_publique explicites sont présentes.)
  3. Vérification crypto : pour chaque signature de la preuve, vérifier quelle signe bien hash-nonce (hash du challenge + nonce) avec la cle_publique indiquée (secp256k1).
  4. Conformité validateurs : toutes les signatures doivent provenir de clés autorisées ; au moins une signature valide est requise.
  5. Anti-rejeu : nonce unique (cache nonce_vus), fenêtre temporelle sur le timestamp du challenge.

Aucune autorité centrale : la décision daccepter ou refuser la session repose uniquement sur ces vérifications locales.

Politique anti-rejeu

  • Nonce unique : chaque preuve utilise un nonce. Le service maintient un cache des nonces déjà vus (ex. NonceCache). Si un nonce est rejoué dans la fenêtre TTL, la preuve est refusée (X_NONCE_REUSED).
  • Fenêtre timestamp : le timestamp du challenge doit être dans une fenêtre acceptable (ex. ±5 min). Sinon refus (X_TIMESTAMP_OUT_OF_WINDOW).
  • Cache nonce_vus : persistance optionnelle (mémoire, IndexedDB, Redis, etc.). Le package fournit un cache en mémoire avec TTL configurable ; le service peut le remplacer par un stockage adapté.

Implémentation

Le package service-login-verify fournit :

  • verifyLoginProof(proof, context) : vérification complète (crypto, clés autorisées, timestamp, nonce).
  • NonceCache : cache anti-rejeu en mémoire (TTL configurable).
  • buildAllowedPubkeysFromValidateurs(validateurs) : extraction des cle_publique depuis les validateurs de laction login.

Le service (parent) :

  1. Reçoit contrat + contrats fils (channel ou défaut).
  2. Extrait laction login et ses validateurs, construit allowedPubkeys via buildAllowedPubkeysFromValidateurs.
  3. Maintient une NonceCache (ou équivalent).
  4. À réception de login-proof, appelle verifyLoginProof(proof, { allowedPubkeys, nonceCache, timestampWindowMs }).
  5. Si accept: true → ouvrir la session ; sinon → refuser et optionnellement informer lutilisateur (ex. via postMessage vers liframe).

Limites

  • Validateurs sans cle_publique (uniquement pair_uuid) : le service ne peut pas vérifier les clés autorisées. Il faut au moins une cle_publique dans signatures_obligatoires pour une vérification stricte côté service.
  • Le service ne déchiffre pas le challenge ; il vérifie uniquement les signatures et lanti-rejeu.

Utilisation

import {
  verifyLoginProof,
  NonceCache,
  buildAllowedPubkeysFromValidateurs,
} from 'service-login-verify';

const nonceCache = new NonceCache(3600000);
const allowedPubkeys = buildAllowedPubkeysFromValidateurs(actionLogin.validateurs_action);

window.addEventListener('message', (event) => {
  if (event.data?.type !== 'login-proof') return;
  const result = verifyLoginProof(event.data.payload, {
    allowedPubkeys,
    nonceCache,
    timestampWindowMs: 300000,
  });
  if (result.accept) {
    // ouvrir session
  } else {
    // refuser (result.reason)
  }
});

Références

  • features/userwallet-contrat-login-reste-a-faire.md (§ 3.7)
  • userwallet/docs/specs.md (graphe, validateurs, anti-rejeu)
  • service-login-verify/ : implémentation (package à la racine du dépôt).
  • website-skeleton/ : squelette de site qui intègre liframe et vérifie les preuves.