feat: persist wallet session across page refreshes #76

Open
sameh-farouk wants to merge 1 commit from feature/vault-session-persistence into development
Member

Summary

Currently every page refresh requires re-entering the mnemonic to log in. This PR adds seamless session persistence using the existing vault system.

How it works

Two-tier storage:

  • sessionStorage["vault_password"] — tab lifetime, enables silent auto-restore on page refresh
  • localStorage["active_vault_session"] — cross-session vault pointer (account ID + key type, no secrets)

User flows:

Event Behavior
First login (no vault) VaultSavePrompt offers to encrypt credentials
Page refresh Silent restore from sessionStorage — no prompt
Browser close + reopen "Unlock" button in navbar — enter vault password
Cancel unlock Falls back to mnemonic LoginModal
Logout Clears sessionStorage, keeps vault pointer — button shows "Unlock"
Vault removal Clears all session indicators

Changes

File Change
login.rs Session helpers (localStorage + sessionStorage), VaultSavePrompt component, VaultUnlockModal component, logout clears sessionStorage, Login button shows "Unlock" when vault exists
main.rs Silent restore on startup via use_future, vault save prompt trigger, global vault_saved_signal context, identity page vault save/remove set session indicators

Security

  • Mnemonic never stored in plaintext — only encrypted in IndexedDB vault
  • sessionStorage holds vault password for tab lifetime only (same attack surface as in-memory WalletState)
  • localStorage holds only vault account ID + key type (public info)
  • Logout clears sessionStorage; browser close clears it automatically

Reused existing code

  • vault_load() — implemented but never called until now
  • vault_save(), vault_exists(), validate_vault_password()
  • WalletState::from_mnemonic() for wallet reconstruction
  • All modal CSS classes (modal-overlay, login-modal, etc.)

Test plan

  • Login with mnemonic → VaultSavePrompt appears → save with password
  • Page refresh → silent restore, wallet connected, no prompt
  • Browser close + reopen → "Unlock" button → enter password → connected
  • Cancel unlock → falls back to mnemonic LoginModal
  • Logout → "Unlock" button persists → click → enter password → connected
  • Identity page shows vault saved immediately after VaultSavePrompt
  • Delete vault from identity page → clears session → "Login" button returns
## Summary Currently every page refresh requires re-entering the mnemonic to log in. This PR adds seamless session persistence using the existing vault system. ## How it works **Two-tier storage:** - `sessionStorage["vault_password"]` — tab lifetime, enables silent auto-restore on page refresh - `localStorage["active_vault_session"]` — cross-session vault pointer (account ID + key type, no secrets) **User flows:** | Event | Behavior | |---|---| | First login (no vault) | VaultSavePrompt offers to encrypt credentials | | Page refresh | Silent restore from sessionStorage — no prompt | | Browser close + reopen | "Unlock" button in navbar — enter vault password | | Cancel unlock | Falls back to mnemonic LoginModal | | Logout | Clears sessionStorage, keeps vault pointer — button shows "Unlock" | | Vault removal | Clears all session indicators | ## Changes | File | Change | |---|---| | `login.rs` | Session helpers (localStorage + sessionStorage), VaultSavePrompt component, VaultUnlockModal component, logout clears sessionStorage, Login button shows "Unlock" when vault exists | | `main.rs` | Silent restore on startup via `use_future`, vault save prompt trigger, global `vault_saved_signal` context, identity page vault save/remove set session indicators | ## Security - Mnemonic never stored in plaintext — only encrypted in IndexedDB vault - sessionStorage holds vault password for tab lifetime only (same attack surface as in-memory WalletState) - localStorage holds only vault account ID + key type (public info) - Logout clears sessionStorage; browser close clears it automatically ## Reused existing code - `vault_load()` — implemented but never called until now - `vault_save()`, `vault_exists()`, `validate_vault_password()` - `WalletState::from_mnemonic()` for wallet reconstruction - All modal CSS classes (`modal-overlay`, `login-modal`, etc.) ## Test plan - [x] Login with mnemonic → VaultSavePrompt appears → save with password - [x] Page refresh → silent restore, wallet connected, no prompt - [x] Browser close + reopen → "Unlock" button → enter password → connected - [x] Cancel unlock → falls back to mnemonic LoginModal - [x] Logout → "Unlock" button persists → click → enter password → connected - [x] Identity page shows vault saved immediately after VaultSavePrompt - [x] Delete vault from identity page → clears session → "Login" button returns
feat: persist wallet session across page refreshes
All checks were successful
Test / check (pull_request) Successful in 5m56s
290f3b9951
Two-tier session storage for seamless wallet persistence:

- sessionStorage["vault_password"]: tab-lifetime, silent auto-restore
  on page refresh without any prompt
- localStorage["active_vault_session"]: cross-session vault pointer
  (account ID + key type, no secrets), triggers VaultUnlockModal on
  fresh browser session

User flows:
- First login (no vault): VaultSavePrompt offers to encrypt credentials
- Page refresh: silent restore from sessionStorage (no interaction)
- Browser close + reopen: VaultUnlockModal prompts for vault password
- Logout: clears sessionStorage, keeps vault pointer — Login button
  shows "Unlock" instead of "Login" for returning users
- Vault removal: clears all session indicators

Login button shows "Unlock" when vault exists (password-only login)
or "Login" when no vault (mnemonic entry). Cancel on unlock falls
back to mnemonic login.
All checks were successful
Test / check (pull_request) Successful in 5m56s
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feature/vault-session-persistence:feature/vault-session-persistence
git switch feature/vault-session-persistence

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch development
git merge --no-ff feature/vault-session-persistence
git switch feature/vault-session-persistence
git rebase development
git switch development
git merge --ff-only feature/vault-session-persistence
git switch feature/vault-session-persistence
git rebase development
git switch development
git merge --no-ff feature/vault-session-persistence
git switch development
git merge --squash feature/vault-session-persistence
git switch development
git merge --ff-only feature/vault-session-persistence
git switch development
git merge feature/vault-session-persistence
git push origin development
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
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
mycelium/www_migrate_mycelium!76
No description provided.