Secure Token Storage

Storing Tokens with expo-secure-store

A refresh token is as good as a password for as long as it lives, so it goes where Secure Storage for Secrets put secrets: expo-secure-store, encrypted with a key in the Android Keystore. src/storage/token.ts gained saveTokens(), readTokens() and forgetTokens(), which keep the pair as one JSON value under booknest.tokens, with an absolute expiresAt rather than the relative expires_in the server sent. After signing in, the app's private preferences file shows what the Keystore key protects:

The stored tokens, as the file on the phone holds themShell
adb -s emulator-5554 shell run-as com.anonymous.booknest \
  cat shared_prefs/SecureStore.xml | cut -c1-95
Output
<map>
    <string name="key_v1-booknest.tokens">{&quot;ct&quot;:&quot;HbLjo4vCYV2FxFggXSD\/QclwNV8N+t
</map>

The value is AES-GCM ciphertext (ct, with its IV in the same JSON); the key never leaves the Keystore, so a copied file or a restored backup yields nothing readable. Never put tokens in MMKV 18,748 or AsyncStorage 5,070 , and never log them. Keep access tokens short-lived (BookNest's last 15 minutes) and delete both on sign-out. On iOS, Keychain items survive uninstalling the app, so a reinstalled app may find an old sign-in.