7.8 KiB
Remember Me Feature
Date: October 10, 2025 Status: ✅ IMPLEMENTED
Overview
The "Remember Me" feature allows users to stay logged in across app restarts. When enabled, the authentication token is saved to persistent secure storage. When disabled, the token is only kept in memory for the current session.
How It Works
When Remember Me is CHECKED (✅)
User logs in with Remember Me enabled
↓
Token saved to SecureStorage (persistent)
↓
Token set in DioClient (current session)
↓
App closes
↓
App reopens
↓
Token loaded from SecureStorage
↓
User auto-logged in ✅
When Remember Me is UNCHECKED (❌)
User logs in with Remember Me disabled
↓
Token NOT saved to SecureStorage
↓
Token set in DioClient (current session only)
↓
App closes
↓
App reopens
↓
No token in SecureStorage
↓
User sees login page ✅
Implementation Details
1. Login Page UI
File: lib/features/auth/presentation/pages/login_page.dart
class _LoginPageState extends ConsumerState<LoginPage> {
bool _rememberMe = false; // Default: unchecked
// Checkbox UI
Checkbox(
value: _rememberMe,
onChanged: (value) {
setState(() {
_rememberMe = value ?? false;
});
},
),
// Pass rememberMe to login
final success = await ref.read(authProvider.notifier).login(
email: _emailController.text.trim(),
password: _passwordController.text,
rememberMe: _rememberMe, // ✅ Pass the value
);
}
2. Auth Provider
File: lib/features/auth/presentation/providers/auth_provider.dart
/// Login user
Future<bool> login({
required String email,
required String password,
bool rememberMe = false, // ✅ Accept rememberMe parameter
}) async {
final result = await _repository.login(
email: email,
password: password,
rememberMe: rememberMe, // ✅ Pass to repository
);
// ... rest of logic
}
3. Auth Repository Interface
File: lib/features/auth/domain/repositories/auth_repository.dart
abstract class AuthRepository {
Future<Either<Failure, AuthResponse>> login({
required String email,
required String password,
bool rememberMe = false, // ✅ Added parameter
});
}
4. Auth Repository Implementation
File: lib/features/auth/data/repositories/auth_repository_impl.dart
@override
Future<Either<Failure, AuthResponse>> login({
required String email,
required String password,
bool rememberMe = false,
}) async {
try {
final authResponse = await remoteDataSource.login(loginDto);
// ✅ Conditional token saving based on rememberMe
if (rememberMe) {
await secureStorage.saveAccessToken(authResponse.accessToken);
print('Token saved to secure storage (persistent)');
} else {
print('Token NOT saved (session only)');
}
// Always set token for current session
dioClient.setAuthToken(authResponse.accessToken);
return Right(authResponse);
} catch (e) {
// Error handling
}
}
User Experience
Scenario 1: Remember Me Enabled
- User opens app → Sees login page
- User enters credentials → Checks "Remember me"
- User clicks Login → Logs in successfully
- User uses app → All features work
- User closes app completely
- User reopens app next day → Automatically logged in! ✅
- No need to enter credentials again
Scenario 2: Remember Me Disabled
- User opens app → Sees login page
- User enters credentials → Does NOT check "Remember me"
- User clicks Login → Logs in successfully
- User uses app → All features work
- User closes app completely
- User reopens app → Shows login page ✅
- User must enter credentials again
Security Considerations
Secure Storage
- iOS: Uses Keychain (encrypted, secure)
- Android: Uses EncryptedSharedPreferences (encrypted)
- Token is encrypted at rest on device
Session-Only Mode
- When Remember Me is disabled, token only exists in memory
- Token cleared when app closes
- More secure for shared/public devices
Best Practices
- ✅ Tokens stored in secure storage (not plain SharedPreferences)
- ✅ User controls persistence via checkbox
- ✅ Token cleared on logout (always)
- ✅ Session expires based on backend JWT expiration
Testing the Feature
Test 1: Remember Me Enabled
1. Open app
2. Login with Remember Me CHECKED
3. Close app completely (swipe from recent apps)
4. Reopen app
Expected: Automatically logged in to MainScreen
Test 2: Remember Me Disabled
1. Open app
2. Login with Remember Me UNCHECKED
3. Close app completely
4. Reopen app
Expected: Shows LoginPage, must login again
Test 3: Logout Clears Token
1. Login with Remember Me CHECKED
2. Close and reopen app (should auto-login)
3. Go to Settings → Logout
4. Close and reopen app
Expected: Shows LoginPage (token was cleared)
Test 4: Toggle Behavior
1. Login with Remember Me UNCHECKED
2. Close and reopen (shows login)
3. Login again with Remember Me CHECKED
4. Close and reopen
Expected: Auto-logged in (token now saved)
Debug Logs
When you login, you'll see these logs:
Remember Me = true
🔐 Repository: Starting login (rememberMe: true)...
🔐 Repository: Got response, token length=xxx
🔐 Repository: Token saved to secure storage (persistent)
🔐 Repository: Token set in DioClient
Remember Me = false
🔐 Repository: Starting login (rememberMe: false)...
🔐 Repository: Got response, token length=xxx
🔐 Repository: Token NOT saved (session only - rememberMe is false)
🔐 Repository: Token set in DioClient
Token Lifecycle
With Remember Me Enabled
Login → Token saved to SecureStorage + DioClient
↓
App running → Token in DioClient (API calls work)
↓
App closed → Token in SecureStorage (persisted)
↓
App opened → Token loaded from SecureStorage → Set in DioClient
↓
Auto-login → User sees MainScreen
Without Remember Me
Login → Token ONLY in DioClient (not saved)
↓
App running → Token in DioClient (API calls work)
↓
App closed → Token lost (not persisted)
↓
App opened → No token in SecureStorage
↓
Shows LoginPage → User must login again
Files Modified
-
✅
lib/features/auth/presentation/pages/login_page.dart- Pass
rememberMe: _rememberMeto login method
- Pass
-
✅
lib/features/auth/presentation/providers/auth_provider.dart- Added
bool rememberMe = falseparameter to login method
- Added
-
✅
lib/features/auth/domain/repositories/auth_repository.dart- Added
bool rememberMe = falseparameter to login signature
- Added
-
✅
lib/features/auth/data/repositories/auth_repository_impl.dart- Conditional token saving:
if (rememberMe) { save token }
- Conditional token saving:
Common Questions
Q: What's the default behavior?
A: Default is rememberMe = false (unchecked). User must explicitly check the box to enable.
Q: Is it secure?
A: Yes! Tokens are stored in platform-specific secure storage (Keychain on iOS, EncryptedSharedPreferences on Android).
Q: What happens on logout?
A: Logout always clears the token from secure storage, regardless of Remember Me state.
Q: Does the token expire?
A: Yes, tokens expire based on your backend JWT configuration. When expired, user must login again.
Q: Can I change the default to checked?
A: Yes, change bool _rememberMe = false; to bool _rememberMe = true; in login_page.dart.
Summary
✅ Remember Me checkbox is now functional ✅ Token persistence controlled by user preference ✅ Secure storage used for token encryption ✅ Session-only mode available for shared devices ✅ Debug logging shows token save/skip behavior
The Remember Me feature is complete and ready to use! 🚀