PD-238 — Endpoints de gestion MFA utilisateur¶
1. Objectif¶
Décrire le contrat canonique des endpoints backend permettant a un utilisateur authentifie de : - consulter l'etat MFA ; - activer le MFA TOTP (init + verification) ; - desactiver le MFA ; - regenerer les codes de recuperation ; - se re-authentifier pour operations sensibles.
2. Périmètre / Hors périmètre¶
Inclus¶
- Endpoint
GET /user/mfa/status. - Endpoint
POST /user/mfa/totp/init. - Endpoint
POST /user/mfa/totp/verify. - Endpoint
POST /user/mfa/disable. - Endpoint
POST /user/mfa/recovery/regenerate. - Endpoint
POST /auth/reauth. - Authentification JWT obligatoire pour
/user/mfa/*. - Authentification JWT obligatoire pour
POST /auth/reauth. - Re-authentification obligatoire pour la desactivation MFA et la regeneration des codes.
- Delegation a Keycloak Admin API pour la gestion MFA.
- Contrat d'API compatible avec PD-106.
- Rate limiting applique aux endpoints MFA.
Exclu¶
- Validation MFA a l'authentification (PD-27).
- Gestion de profil (PD-32).
- Changement de mot de passe.
- Suppression de compte.
- Logout / gestion de session.
- MFA par SMS, email ou WebAuthn.
- Implementation TOTP native cote ProbatioVault.
- Stockage de secrets MFA cote ProbatioVault.
3. Définitions¶
- MFA : authentification multi-facteur.
- TOTP : mot de passe a usage unique base sur le temps (RFC 6238, gere par Keycloak).
- Etat MFA : etat du MFA pour l'utilisateur courant (
enabled,method,configuredAt). - method : type de MFA configure. Valeurs possibles :
TOTP. Extensible ulterieurement. - configuredAt : date d'activation du MFA, format ISO 8601 UTC (ex:
2026-02-06T14:30:00Z). - Re-authentification : preuve recente d'identite pour operation sensible via
POST /auth/reauth. - Reauth token : JWT signe avec claims
sub,purpose="reauth",exp(5 minutes). - Operations sensibles : desactivation MFA, regeneration des codes de recuperation.
- Codes de recuperation : codes a usage unique emis par Keycloak (15 codes par defaut).
- Affichage unique : les codes de recuperation ne sont retournes qu'une seule fois apres generation/regeneration.
- Compatibilite PD-106 : endpoints et payloads conformes aux formats attendus par PD-106.
- Hors perimetre : exigence non verifiable dans PD-238 seul et devant etre prouvee par un artefact externe.
4. Invariants (non négociables)¶
| ID | Règle | Justification |
|---|---|---|
| INV-238-01 | Tous les endpoints /user/mfa/* DOIVENT exiger un JWT valide. | Empêche l'acces anonyme. |
| INV-238-02 | Un utilisateur NE DOIT pouvoir consulter/modifier que son propre MFA. | Empêche l'acces croise. |
| INV-238-03 | GET /user/mfa/status DOIT retourner {enabled, method, configuredAt} et method DOIT valoir TOTP (seule valeur supportée dans PD-238). | Compatibilite PD-106. |
| INV-238-04 | POST /user/mfa/totp/init DOIT retourner secret, qrCodeUri, expiresAt. | Activation TOTP conforme. |
| INV-238-05 | POST /user/mfa/totp/verify DOIT activer le MFA uniquement si le code est valide. | Evite activation sans preuve. |
| INV-238-06 | POST /user/mfa/disable DOIT exiger un reauth token valide. | Protege operations sensibles. |
| INV-238-07 | POST /user/mfa/recovery/regenerate DOIT exiger un reauth token valide et invalider les anciens codes. | Protege operation sensible et evite coexistence codes. |
| INV-238-08 | Les codes de recuperation DOIVENT etre retournes uniquement apres activation/regeneration (affichage unique). | Reduit exposition des codes. |
| INV-238-09 | Le secret TOTP et les codes de recuperation NE DOIVENT jamais etre loggues. | Protection des secrets. |
| INV-238-10 | Le backend ProbatioVault NE DOIT pas stocker les secrets MFA. | Conformite PD-27 §I3. |
| INV-238-11 | Les endpoints MFA DOIVENT etre soumis au rate limiting global. | Prevention brute force. |
| INV-238-12 | POST /auth/reauth DOIT retourner un reauthToken JWT avec sub, purpose="reauth", exp = 5 minutes. | Garantit reauth stateless. |
| INV-238-13 | Toute erreur metier/validation/auth DOIT retourner un echec explicite sans effet partiel silencieux. | Auditabilite. |
| INV-238-14 | HORS PERIMETRE PD-238 : preuve juridique exhaustive RGPD et audit Keycloak admin doivent etre fournis par artefacts conformite. | Non prouvable via endpoints seuls. |
| INV-238-15 | POST /auth/reauth DOIT exiger un JWT valide. | Empêche l'acces anonyme. |
5. Flux nominaux¶
F-238-01 — Lecture etat MFA¶
- L'utilisateur appelle
GET /user/mfa/statusavec JWT valide. - Le systeme identifie l'utilisateur courant.
- Le systeme interroge Keycloak et retourne l'etat MFA.
F-238-02 — Initialisation TOTP¶
- L'utilisateur appelle
POST /user/mfa/totp/initavec JWT valide. - Le systeme initie la configuration TOTP via Keycloak.
- Le systeme retourne
secret,qrCodeUri,expiresAt.
F-238-03 — Verification TOTP¶
- L'utilisateur appelle
POST /user/mfa/totp/verifyavec JWT valide et code. - Le systeme verifie le code via Keycloak.
- En cas de succes, le MFA est active et les codes de recuperation sont retournes une seule fois.
F-238-04 — Desactivation MFA¶
- L'utilisateur appelle
POST /user/mfa/disableavec JWT valide etX-Reauth-Tokenvalide. - Le systeme desactive le MFA via Keycloak.
- La reponse indique
enabled: false.
F-238-05 — Regeneration codes de recuperation¶
- L'utilisateur appelle
POST /user/mfa/recovery/regenerateavec JWT valide etX-Reauth-Tokenvalide. - Le systeme regenere les codes via Keycloak et invalide les anciens.
- Les nouveaux codes sont retournes une seule fois.
F-238-06 — Re-authentification¶
- L'utilisateur appelle
POST /auth/reauthavec son mot de passe. - Le systeme verifie l'identite et retourne un
reauthTokenavecexpiresAt.
5bis. Diagrammes Mermaid¶
D-238-01 — Diagramme d'etats MFA utilisateur¶
Etats du MFA pour un utilisateur donne. Transitions gouvernees par INV-238-05 (activation uniquement si code valide), INV-238-06 (desactivation exige reauth), INV-238-07 (regeneration exige reauth et invalide anciens codes).
stateDiagram-v2
[*] --> MFA_DISABLED
MFA_DISABLED --> TOTP_INIT_PENDING : POST /user/mfa/totp/init\n[INV-238-04: retourne secret, qrCodeUri, expiresAt]
TOTP_INIT_PENDING --> MFA_ENABLED : POST /user/mfa/totp/verify (code valide)\n[INV-238-05: activation + recoveryCodes]
TOTP_INIT_PENDING --> MFA_DISABLED : expiresAt depasse\nou POST /user/mfa/totp/verify (code invalide, abandon)
TOTP_INIT_PENDING --> TOTP_INIT_PENDING : POST /user/mfa/totp/verify (code invalide)\n[INV-238-13: echec explicite, pas d'effet partiel]
MFA_ENABLED --> MFA_DISABLED : POST /user/mfa/disable + reauth token\n[INV-238-06]
MFA_ENABLED --> MFA_ENABLED : POST /user/mfa/recovery/regenerate + reauth token\n[INV-238-07: anciens codes invalides] D-238-02 — Diagramme de sequence : activation TOTP (F-238-02 + F-238-03)¶
Flux multi-service couvrant l'initialisation et la verification TOTP. Le backend ne stocke aucun secret MFA (INV-238-10), Keycloak est la source de verite.
sequenceDiagram
participant U as Utilisateur
participant B as Backend ProbatioVault
participant KC as Keycloak Admin API
Note over U,KC: Phase 1 — Initialisation TOTP (F-238-02)
U->>B: POST /user/mfa/totp/init [JWT]
activate B
B->>B: Valider JWT [INV-238-01]
B->>B: Identifier utilisateur courant [INV-238-02]
B->>KC: Initier config TOTP (userId)
activate KC
KC-->>B: secret, qrCodeUri, expiresAt
deactivate KC
B-->>U: 200 {secret, qrCodeUri, expiresAt} [INV-238-04]
deactivate B
Note over U: L'utilisateur scanne le QR code<br/>dans son app TOTP
Note over U,KC: Phase 2 — Verification TOTP (F-238-03)
U->>B: POST /user/mfa/totp/verify {code} [JWT]
activate B
B->>B: Valider JWT [INV-238-01]
B->>KC: Verifier code TOTP (userId, code)
activate KC
alt Code valide
KC-->>B: OK + recoveryCodes (15 codes)
B-->>U: 200 {enabled: true, recoveryCodes} [INV-238-05, INV-238-08]
else Code invalide
KC-->>B: INVALID
B-->>U: 400 ERR-238-TOTP-INVALID [INV-238-13]
end
deactivate KC
deactivate B
Note over B: Secret TOTP et recoveryCodes<br/>jamais loggues [INV-238-09]<br/>Jamais stockes cote backend [INV-238-10] D-238-03 — Diagramme de sequence : re-authentification + operation sensible (F-238-06 + F-238-04)¶
Flux de re-authentification prealable a une operation sensible (desactivation MFA). Applicable aussi a la regeneration des codes (F-238-05).
sequenceDiagram
participant U as Utilisateur
participant B as Backend ProbatioVault
participant KC as Keycloak Admin API
Note over U,KC: Phase 1 — Re-authentification (F-238-06)
U->>B: POST /auth/reauth {password} [JWT]
activate B
B->>B: Valider JWT [INV-238-15]
B->>B: Verifier mot de passe
alt Mot de passe valide
B->>B: Signer reauthToken JWT<br/>{sub, purpose="reauth", exp=5min} [INV-238-12]
B-->>U: 200 {reauthToken, expiresAt}
else Mot de passe invalide
B-->>U: 401 ERR-238-REAUTH-FAILED
end
deactivate B
Note over U,KC: Phase 2 — Desactivation MFA (F-238-04)
U->>B: POST /user/mfa/disable [JWT + X-Reauth-Token]
activate B
B->>B: Valider JWT [INV-238-01]
B->>B: Valider reauthToken (purpose, exp) [INV-238-06]
B->>KC: Desactiver MFA (userId)
activate KC
KC-->>B: OK
deactivate KC
B-->>U: 200 {enabled: false}
deactivate B 6. Cas d'erreur¶
| Code erreur | Condition | Comportement attendu |
|---|---|---|
| ERR-238-UNAUTHENTICATED | JWT absent/invalide | Refus d'acces ; aucune operation effectuee. |
| ERR-238-UNAUTHORIZED-REAUTH | Reauth token absent/invalide/expire | Refus operation sensible. |
| ERR-238-FORBIDDEN-CROSS-ACCESS | Tentative d'acces MFA d'un autre utilisateur | Refus explicite ; aucune fuite. |
| ERR-238-TOTP-INIT-FAILED | Echec initialisation TOTP Keycloak | Message explicite ; aucune activation. |
| ERR-238-TOTP-INVALID | Code TOTP invalide | Message explicite ; MFA non active. |
| ERR-238-MFA-DISABLE-FAILED | Echec desactivation MFA | Message explicite ; MFA reste actif. |
| ERR-238-RECOVERY-REGEN-FAILED | Echec regeneration codes | Message explicite ; anciens codes restent valides. |
| ERR-238-RATE-LIMIT | Seuil global depasse | Refus explicite ; aucune operation effectuee. |
| ERR-238-INTERNAL | Erreur interne non metier | Refus explicite ; aucun succes affiche. |
| ERR-238-REAUTH-FAILED | Mot de passe invalide | Message explicite ; aucun token emis. |
7. Critères d'acceptation (testables)¶
| ID | Critère | Observable |
|---|---|---|
| CA-238-01 | GET /user/mfa/status sans JWT est refuse. | Reponse erreur auth. |
| CA-238-02 | POST /user/mfa/totp/init sans JWT est refuse. | Reponse erreur auth. |
| CA-238-03 | POST /user/mfa/totp/verify sans JWT est refuse. | Reponse erreur auth. |
| CA-238-04 | POST /user/mfa/disable sans reauth token est refuse. | Reponse erreur reauth. |
| CA-238-05 | POST /user/mfa/recovery/regenerate sans reauth token est refuse. | Reponse erreur reauth. |
| CA-238-06 | GET /user/mfa/status retourne {enabled, method, configuredAt}. | Inspection reponse JSON. |
| CA-238-07 | POST /user/mfa/totp/init retourne secret, qrCodeUri, expiresAt. | Inspection reponse JSON. |
| CA-238-08 | POST /user/mfa/totp/verify active MFA uniquement si code valide. | Etat MFA + reponse enabled: true. |
| CA-238-09 | Codes de recuperation retournes uniquement apres activation/regeneration. | Absence en dehors de ces reponses. |
| CA-238-10 | Regeneration invalide anciens codes. | Ancien code refuse. |
| CA-238-11 | Desactivation MFA exige reauth token valide. | Operation refusee sans reauth. |
| CA-238-12 | Secrets TOTP et recovery codes ne figurent pas dans les logs. | Audit logs. |
| CA-238-13 | Endpoints MFA soumis au rate limiting. | Reponse rate limit. |
| CA-238-14 | Reauth token retourne sub, purpose="reauth", exp (5 min). | Inspection JWT. |
| CA-238-15 | HORS PERIMETRE PD-238 : preuve RGPD/Keycloak admin via artefacts externes. | Presence artefact externe. |
| CA-238-16 | POST /auth/reauth sans JWT est refuse. | Reponse erreur auth. |
8. Scénarios de test (Given / When / Then)¶
Scenario 1 — Etat MFA nominal¶
GIVEN utilisateur authentifie. WHEN GET /user/mfa/status. THEN la reponse contient enabled, method, configuredAt.
Scenario 2 — Init TOTP nominale¶
GIVEN utilisateur authentifie. WHEN POST /user/mfa/totp/init. THEN la reponse contient secret, qrCodeUri, expiresAt.
Scenario 3 — Verify TOTP nominal¶
GIVEN utilisateur authentifie et secret init. WHEN POST /user/mfa/totp/verify avec code valide. THEN MFA devient actif et recoveryCodes sont retournes une seule fois.
Scenario 4 — Verify TOTP invalide¶
GIVEN utilisateur authentifie. WHEN POST /user/mfa/totp/verify avec code invalide. THEN MFA reste inactif et erreur explicite.
Scenario 5 — Disable MFA avec reauth¶
GIVEN utilisateur authentifie avec MFA actif et reauth token valide. WHEN POST /user/mfa/disable. THEN MFA est desactive.
Scenario 6 — Regen recovery codes avec reauth¶
GIVEN utilisateur authentifie avec MFA actif et reauth token valide. WHEN POST /user/mfa/recovery/regenerate. THEN nouveaux codes retournes, anciens invalides.
Scenario 7 — Reauth nominal¶
GIVEN utilisateur authentifie. WHEN POST /auth/reauth avec mot de passe valide. THEN reauthToken valide est retourne avec exp 5 min.
Scenario 8 — Rate limit¶
GIVEN utilisateur authentifie. WHEN depassement seuil requetes MFA. THEN reponse ERR-238-RATE-LIMIT.
Scenario 9 — Cross-access¶
GIVEN U1 et U2. WHEN U1 tente action MFA sur U2. THEN refus explicite.
Scenario 10 — Hors perimetre RGPD¶
GIVEN perimetre PD-238. WHEN preuve RGPD requise. THEN reference artefact externe.
Scenario 11 — Reauth mot de passe invalide¶
GIVEN utilisateur authentifie. WHEN POST /auth/reauth avec mot de passe invalide. THEN erreur explicite et aucun reauthToken emis.
9. Hypothèses explicites¶
| ID | Hypothèse | Impact si faux |
|---|---|---|
| H-238-01 | Keycloak Admin API est disponible et authentifiable via service account. | Endpoints MFA inoperants. |
| H-238-02 | Les claims OIDC permettent d'identifier l'utilisateur courant. | Acces croise possible. |
| H-238-03 | Le backend peut valider un reauth token JWT signe. | Operations sensibles non securisables. |
| H-238-04 | Le rate limiting global est actif sur /user/mfa/*. | CA-238-13 non atteignable. |
| H-238-05 | Keycloak retourne 15 recovery codes par defaut. | Incoherence avec contrat PD-106. |
| H-238-06 | L'artefact RGPD/Keycloak admin est gere hors PD-238. | CA-238-15 non demonstrable. |
10. Points à clarifier¶
- Format exact des erreurs Keycloak a normaliser en ERR-238-*.
- Delai de validite du
qrCodeUri(expiresAt) si different de Keycloak par defaut. - Format exact du
configuredAtretourne par Keycloak. - Politique de rotation des recovery codes (regeneration illimitee ou seuil).
Références¶
- Epic : EPIC-182
- JIRA : PD-238
- Repos concernés : ProbatioVault-backend
- Documents associés : PD-27, PD-106, PD-32