Multi-Account Support
Managing multiple user sessions within the application
GUIDE-09: Multi-Account Support Implementation Guide
Overview
This guide provides patterns for allowing users to be logged into multiple accounts simultaneously within the application and switch between them easily.
Key components of this approach:
AccountInterface: Defines the structure for storing individual account details, including tokens and user information.useAccountsStore(Zustand): A dedicated Zustand store manages the list of all logged-in accounts and keeps track of the currently active account ID.- Secure Persistence: The
useAccountsStore(containing sensitive tokens) must be persisted securely using Zustand's persist middleware configured withsecureStorage. - Modified Auth Flow: The standard login/register success handlers (
useAuthoruseSocialLoginMutation) are updated to add or update accounts in theaccountsSlice. switchAccountLogic: A mechanism to change the active account, involving updating Zustand state, the API client header, and potentially fetching data for the newly active account.
When To Use
Apply these patterns when your application needs to support users logged into multiple accounts concurrently (e.g., personal and work accounts) and allow seamless switching without repeated logins.
Prerequisites
- Core Auth Flow: The standard authentication flow (GUIDE-05) with Zustand (
useAuthStore) and TanStack Query mutations must be implemented. - Zustand Persist Middleware: Zustand's persist middleware should be configured with appropriate storage (GUIDE-02).
- Secure Storage Module:
secureStoragemodule (DOC-04) must be available. - Persist Configuration: Zustand's persist middleware must be configured with
secureStorageto securely store the accounts data containing tokens.
Implementation Patterns
1. Account Interface
Define a type for storing account information.
2. Ensuring Secure Storage for Zustand Persist
Configure Zustand's persist middleware to use expo-secure-store through our secureStorage module.
3. Accounts Store (Zustand)
Create a Zustand store to manage the list of accounts and the active ID.
4. No Additional Configuration Needed
With Zustand's persist middleware already configured in our useAccountsStore, no additional persistence setup is required. The middleware handles:
- Automatic persistence of state changes
- Secure storage through our custom storage adapter
- Hydration on app startup
This approach simplifies our implementation compared to Redux, as we don't need to set up a separate persistence layer.
5. Modify Auth Success Handling
Update the login/register success handler to store account info in both contexts.
6. Implement Account Switching Hook (useSwitchAccount)
Create a dedicated hook for account switching.
7. Account Removal/Logout
Implement an extended logout to handle account removal:
- Implement
removeCurrentAccountinuseAuththat:- Gets the current
activeAccountIdfrom the accounts store. - Call
removeAccount(activeAccountId)from the accounts store actions. - If other accounts remain, call
switchToAccountwith the ID of another account. - If no accounts remain, call the main
logout()function.
- Gets the current
- Implement
logoutAllthat:- Call
clearAccounts()from the accounts store actions. - Call the standard logout flow to clear everything else.
- Call
8. Account Selection UI
Create a profile selector component that displays all available accounts.
Considerations & Challenges
- (Be Aware ❗) Secure Persistence: Ensuring the
accountsSlicecontaining multiple tokens is stored only using thesecurePersistStorageengine is critical. Misconfiguration (e.g., accidentally persisting it via AsyncStorage) could expose all stored tokens. - (Be Aware ❗) Token Refresh: The standard API interceptor (GUIDE-05) typically refreshes the token for the currently active session only. Implementing background refresh for inactive accounts is significantly more complex (managing multiple timers, secure token access) and generally not implemented unless specifically required and carefully designed.
- (Do ✅) State Synchronization: When switching accounts, ensure all relevant user-specific data is cleared/refetched. Use TanStack Query's
queryClient.removeQueriesorqueryClient.invalidateQueriestargeting user-specific keys, andqueryClient.fetchQueryfor immediate essential data reloading. - (Consider 🤔) Backend Support: This pattern assumes the backend issues independent tokens per login and treats each as a separate session. If the backend has its own server-side multi-session management, this client-side approach might need adjustment or simplification.
- (Do ✅) UI/UX: Clearly indicate the active account throughout the app (e.g., in a profile header). Provide an intuitive and easily accessible way to switch accounts (e.g., via profile menu).
- (Do ✅) Error Handling: Implement robust error handling during the
switchAccountprocess, especially if fetching essential data for the new account fails. Decide whether to revert the switch or force a logout.
Related Documents
- GUIDE-05: Authentication Flow Implementation Guide
- GUIDE-02: State Management Implementation Guide (Redux)
- GUIDE-07: Social Login Implementation Guide
- DOC-03: API & State Management Reference
- DOC-04: Security & Offline Framework Reference