Security: SessionManager/OAuthSessionStore apply() → commit() for auth-critical writes #37

Closed
opened 2026-06-22 18:40:14 +00:00 by starsetbyte · 0 comments
Owner

What

SessionManager and OAuthSessionStore use SharedPreferences.edit().apply() (async) for auth-critical writes instead of commit() (sync). If the process dies between the async write and disk flush, tokens and session data are lost.

Affected locations

  • SessionManager.saveSession() — access/refresh JWT + DID + handle
  • SessionManager.saveOAuthSession() — DID + handle + auth mode
  • SessionManager.clearSession() — session wipe
  • SessionManager.saveAppPassword() — app password credentials
  • OAuthSessionStore.clear() — OAuth session wipe
  • OAuthSessionStore.updateTokens() — access/refresh token rotation

Why it matters

apply() returns immediately but writes to disk asynchronously. If the process is killed before the background write completes, the data is never persisted. For auth data (tokens, passwords, session state), this can cause:

  • App appears unauthenticated on restart after a crash
  • Stale session data surviving clearSession() — user thinks they logged out but tokens persist
  • Token rotation silently lost, triggering unnecessary re-auth on next launch

Fix

All apply() calls at the locations above changed to commit(). The OAuth nonce update methods (updateResourceNonce, updateAuthServerNonce) intentionally keep apply() since nonce staleness is recovered automatically (server returns use_dpop_nonce → retry).

Fixed in current working tree.

## What SessionManager and OAuthSessionStore use `SharedPreferences.edit().apply()` (async) for auth-critical writes instead of `commit()` (sync). If the process dies between the async write and disk flush, tokens and session data are lost. ## Affected locations - `SessionManager.saveSession()` — access/refresh JWT + DID + handle - `SessionManager.saveOAuthSession()` — DID + handle + auth mode - `SessionManager.clearSession()` — session wipe - `SessionManager.saveAppPassword()` — app password credentials - `OAuthSessionStore.clear()` — OAuth session wipe - `OAuthSessionStore.updateTokens()` — access/refresh token rotation ## Why it matters `apply()` returns immediately but writes to disk asynchronously. If the process is killed before the background write completes, the data is never persisted. For auth data (tokens, passwords, session state), this can cause: - App appears unauthenticated on restart after a crash - Stale session data surviving `clearSession()` — user thinks they logged out but tokens persist - Token rotation silently lost, triggering unnecessary re-auth on next launch ## Fix All `apply()` calls at the locations above changed to `commit()`. The OAuth nonce update methods (`updateResourceNonce`, `updateAuthServerNonce`) intentionally keep `apply()` since nonce staleness is recovered automatically (server returns `use_dpop_nonce` → retry). **Fixed in current working tree.**
Sign in to join this conversation.
No description provided.