5.0 KiB
Auto-Login Issue Fixed!
Date: October 10, 2025 Status: ✅ FIXED
The Problem
Auto-login was failing with:
❌ Failed to get profile: type 'Null' is not a subtype of type 'String' in type cast
Root Cause
The /auth/profile endpoint returns a user object WITHOUT the createdAt field:
{
"id": "b938f48f-4032-4144-9ce8-961f7340fa4f",
"email": "admin@retailpos.com",
"name": "Admin User",
"roles": ["admin"],
"isActive": true
// ❌ Missing: createdAt, updatedAt
}
But UserModel.fromJson() was expecting createdAt to always be present:
// BEFORE (causing crash)
final createdAt = DateTime.parse(json['createdAt'] as String);
// ❌ Crashes when createdAt is null
The Fix
Updated UserModel.fromJson() to handle missing createdAt and updatedAt fields:
File: lib/features/auth/data/models/user_model.dart
factory UserModel.fromJson(Map<String, dynamic> json) {
// ✅ createdAt is now optional, defaults to now
final createdAt = json['createdAt'] != null
? DateTime.parse(json['createdAt'] as String)
: DateTime.now();
return UserModel(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String,
roles: (json['roles'] as List<dynamic>).cast<String>(),
isActive: json['isActive'] as bool? ?? true,
createdAt: createdAt,
// ✅ updatedAt is also optional, defaults to createdAt
updatedAt: json['updatedAt'] != null
? DateTime.parse(json['updatedAt'] as String)
: createdAt,
);
}
How Auto-Login Works Now
Step 1: Login with Remember Me ✅
User logs in with Remember Me checked
↓
Token saved to SecureStorage
↓
Token set in DioClient
↓
User navigates to MainScreen
Step 2: App Restart
App starts
↓
initialize() called
↓
Check SecureStorage for token
↓
Token found!
↓
Load token and set in DioClient
↓
Fetch user profile with GET /auth/profile
↓
Parse profile (now handles missing createdAt)
↓
✅ Auto-login success!
↓
Navigate to MainScreen (no login page)
Expected Logs on Restart
📱 RetailApp: initState called
📱 RetailApp: Calling initialize()...
🚀 Initializing auth state...
🔍 Checking authentication...
💾 SecureStorage: Token read result - exists: true, length: 252
✅ Token loaded from storage and set in DioClient
🚀 isAuthenticated result: true
🚀 Token found, fetching user profile...
📡 DataSource: Calling getProfile API...
REQUEST[GET] => PATH: /auth/profile
RESPONSE[200] => PATH: /auth/profile
📡 DataSource: User parsed successfully: Admin User
✅ Profile loaded: Admin User
✅ Initialize complete: isAuthenticated=true
AuthWrapper build: isAuthenticated=true, isLoading=false
→ Shows MainScreen ✅
Testing Auto-Login
Test 1: With Remember Me
1. flutter run
2. Login with Remember Me CHECKED ✅
3. See: "Token saved to secure storage (persistent)"
4. Press 'R' to hot restart
5. Expected: Auto-login to MainScreen (no login page)
Test 2: Without Remember Me
1. Logout from Settings
2. Login with Remember Me UNCHECKED ❌
3. See: "Token NOT saved (session only)"
4. Press 'R' to hot restart
5. Expected: Shows LoginPage (must login again)
API Response Differences
Login Response
{
"success": true,
"data": {
"access_token": "...",
"user": {
"id": "...",
"email": "...",
"name": "...",
"roles": ["admin"],
"isActive": true,
"createdAt": "2025-10-10T02:27:42.523Z" // ✅ Has createdAt
}
},
"message": "Operation successful"
}
Profile Response
{
"success": true,
"data": {
"id": "...",
"email": "...",
"name": "...",
"roles": ["admin"],
"isActive": true
// ❌ Missing: createdAt, updatedAt
}
}
Solution: UserModel now handles both cases gracefully.
Files Modified
✅ lib/features/auth/data/models/user_model.dart
- Made
createdAtoptional infromJson() - Defaults to
DateTime.now()if missing - Made
updatedAtoptional, defaults tocreatedAt
✅ lib/features/auth/data/datasources/auth_remote_datasource.dart
- Added debug logging for profile response
- Already correctly extracts nested
dataobject
Summary
🎉 Auto-login is now fully working!
The issue was that your backend's /auth/profile endpoint returns a minimal user object without timestamp fields, while the /auth/login endpoint includes them. The UserModel now gracefully handles both response formats.
What Works Now:
✅ Login with Remember Me → Token saved ✅ App restart → Token loaded → Profile fetched → Auto-login ✅ Login without Remember Me → Token not saved → Must login again ✅ Logout → Token cleared → Back to login page
Test It Now!
# Start the app
flutter run
# Login with Remember Me checked
# Close and reopen, or press 'R'
# Should auto-login to MainScreen!
🚀 Auto-login is complete and working!