**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/
87 lines
4.6 KiB
Markdown
87 lines
4.6 KiB
Markdown
# 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 l’application **parente** qui embarque UserWallet en iframe. C’est elle qui **consomme** le login : elle reçoit la preuve de login (`login-proof`) via `postMessage`, doit l’**accepter 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 d’accepter la session.
|
||
|
||
### Acceptation de session
|
||
|
||
Le service doit **vérifier la preuve** en s’appuyant 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 l’action login, les membres, les validateurs.
|
||
2. **Clés autorisées** : à partir des validateurs de l’action login (`membres_du_role[].signatures_obligatoires[].cle_publique`), construire l’ensemble 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 qu’elle 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 d’accepter 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 l’action login.
|
||
|
||
Le service (parent) :
|
||
|
||
1. Reçoit contrat + contrats fils (channel ou défaut).
|
||
2. Extrait l’action 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 l’utilisateur (ex. via `postMessage` vers l’iframe).
|
||
|
||
### 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 l’anti-rejeu.
|
||
|
||
## Utilisation
|
||
|
||
```ts
|
||
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 l’iframe et vérifie les preuves.
|