Add recovery key rotation in account settings #45

Merged
LHa merged 3 commits from feature/recovery-key-reset into main 2026-08-11 20:01:41 +00:00
Owner

Summary

Implements recovery key rotation (regeneration) for authenticated users with E2EE scheme v2, as requested in #44.

Users can reset/regenerate their E2EE recovery key from Settings → Account → Recovery key while logged in.

Changes

  • Server: POST /api/session/rotate-recovery (and /api/auth/ alias) handler handleRotateRecovery in auth-http-service.js. Verifies current password (authKey as proof), validates E2EE scheme v2, atomically replaces wrappedMkRecovery + recoveryHash + recoveryRotatedAt. Routes registered in core-routes.js.
  • Client: e2eeRotateRecovery() in e2ee-session.js — derives old keys from password, unwraps MK extractable once, generates new recovery key, wraps MK under it, sends to server. app.js wires the UI handlers and a settings-local modal showing the new key with copy + confirm.
  • UI: Recovery key card in settings.html account section.
  • i18n: settings.recoveryKey* keys added to both en.json and de.json.
  • Tests: 3 new tests in auth-http-service.test.mjs (successful rotation, wrong password 401, non-scheme-2 409).

Security model

  • MK does not change during rotation — only wrappedMkRecovery and recoveryHash are replaced server-side. No data re-encryption needed.
  • Current password as proof (not old recovery key) — matches change-password flow; simpler UX when the old recovery key is suspected compromised.
  • Old recovery key stops working immediately (server-side replacement).
  • Current session rotated only (like change-password); other sessions stay active since recovery key is not a session auth means.
  • CSRF protection active (session-scoped route, not in PRE_SESSION_PATHS).

Closes #44

## Summary Implements recovery key rotation (regeneration) for authenticated users with E2EE scheme v2, as requested in #44. Users can reset/regenerate their E2EE recovery key from **Settings → Account → Recovery key** while logged in. ## Changes - **Server**: `POST /api/session/rotate-recovery` (and `/api/auth/` alias) handler `handleRotateRecovery` in `auth-http-service.js`. Verifies current password (authKey as proof), validates E2EE scheme v2, atomically replaces `wrappedMkRecovery` + `recoveryHash` + `recoveryRotatedAt`. Routes registered in `core-routes.js`. - **Client**: `e2eeRotateRecovery()` in `e2ee-session.js` — derives old keys from password, unwraps MK extractable once, generates new recovery key, wraps MK under it, sends to server. `app.js` wires the UI handlers and a settings-local modal showing the new key with copy + confirm. - **UI**: Recovery key card in `settings.html` account section. - **i18n**: `settings.recoveryKey*` keys added to both `en.json` and `de.json`. - **Tests**: 3 new tests in `auth-http-service.test.mjs` (successful rotation, wrong password 401, non-scheme-2 409). ## Security model - **MK does not change** during rotation — only `wrappedMkRecovery` and `recoveryHash` are replaced server-side. No data re-encryption needed. - **Current password as proof** (not old recovery key) — matches change-password flow; simpler UX when the old recovery key is suspected compromised. - **Old recovery key stops working immediately** (server-side replacement). - **Current session rotated only** (like change-password); other sessions stay active since recovery key is not a session auth means. - CSRF protection active (session-scoped route, not in `PRE_SESSION_PATHS`). Closes #44
Introduce POST /api/session/rotate-recovery (and /api/auth/ alias) that
lets an authenticated scheme-2 user rotate their recovery key. The
current password (authKey) serves as proof; the server atomically
replaces wrappedMkRecovery and recoveryHash. The master key does not
change, so no data re-encryption is needed. The current session is
rotated; other sessions remain active because the recovery key is not a
session auth means. Closes #44.
Add e2eeRotateRecovery() to e2ee-session.js: derives current keys from
the password, unwraps the master key extractable once, generates a new
recovery key, wraps the master key under it, and sends the new envelope
to the server.

Wire the settings UI in app.js: open/close field toggles, submitRotate
Recovery handler, and a settings-local modal that displays the new
recovery key once with copy and confirm actions.
Add recovery key rotation UI and i18n strings
Some checks failed
CI / Safe checks (pull_request) Successful in 3m0s
Container images / Build temporary amd64 candidates (push) Failing after 18m35s
Container images / Smoke-test App candidate (push) Has been skipped
Container images / Smoke-test Whisper candidate (push) Has been skipped
Container images / Publish immutable amd64 candidates (push) Has been skipped
ab1e01867c
Add a recovery key card to the account section of the settings page
with password input and confirm button. Add settings.recoveryKey* keys
to both en.json and de.json.
LHa merged commit ab1e01867c into main 2026-08-11 20:01:41 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
TLLX/CHAT-TLLX!45
No description provided.