# Authentication Feature - Quick Reference ## Import ```dart import 'package:minhthu/features/auth/auth.dart'; ``` ## Common Usage Patterns ### 1. Login ```dart ref.read(authProvider.notifier).login(username, password); ``` ### 2. Logout ```dart ref.read(authProvider.notifier).logout(); ``` ### 3. Check if Authenticated ```dart final isAuthenticated = ref.watch(isAuthenticatedProvider); ``` ### 4. Get Current User ```dart final user = ref.watch(currentUserProvider); if (user != null) { print('Logged in as: ${user.username}'); } ``` ### 5. Watch Auth State ```dart final authState = ref.watch(authProvider); if (authState.isLoading) { return LoadingIndicator(); } if (authState.error != null) { return ErrorView(message: authState.error!); } if (authState.isAuthenticated) { return HomeView(user: authState.user!); } return LoginView(); ``` ### 6. Listen to Auth Changes ```dart ref.listen(authProvider, (previous, next) { if (next.isAuthenticated) { context.go('/home'); } else if (next.error != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(next.error!)), ); } }); ``` ## Key Classes ### AuthState ```dart class AuthState { final UserEntity? user; final bool isAuthenticated; final bool isLoading; final String? error; } ``` ### UserEntity ```dart class UserEntity { final String userId; final String username; final String accessToken; final String? refreshToken; } ``` ### LoginRequestModel ```dart final request = LoginRequestModel( username: 'john.doe', password: 'secure123', ); ``` ## Providers | Provider | Type | Description | |----------|------|-------------| | `authProvider` | `StateNotifier` | Main auth state | | `isAuthenticatedProvider` | `bool` | Check auth status | | `currentUserProvider` | `UserEntity?` | Get current user | | `isAuthLoadingProvider` | `bool` | Check loading state | | `authErrorProvider` | `String?` | Get error message | ## API Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/api/v1/auth/login` | POST | Login | | `/api/v1/auth/logout` | POST | Logout | | `/api/v1/auth/refresh` | POST | Refresh token | ## Error Types - `ValidationFailure` - Invalid input - `AuthenticationFailure` - Login failed - `NetworkFailure` - Network error - `ServerFailure` - Server error ## Protected Route Example ```dart class MyPage extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final authState = ref.watch(authProvider); if (!authState.isAuthenticated) { return LoginPage(); } return Scaffold( appBar: AppBar( title: Text('Protected Page'), actions: [ IconButton( icon: Icon(Icons.logout), onPressed: () => ref.read(authProvider.notifier).logout(), ), ], ), body: Center( child: Text('Hello, ${authState.user!.username}!'), ), ); } } ``` ## Common Patterns ### Check Auth on App Start ```dart @override void initState() { super.initState(); Future.microtask(() { ref.read(authProvider.notifier).checkAuthStatus(); }); } ``` ### Show Loading Overlay ```dart if (ref.watch(isAuthLoadingProvider)) { return Stack( children: [ yourContent, LoadingIndicator.overlay(), ], ); } ``` ### Conditional Navigation ```dart ref.listen(authProvider, (previous, next) { if (!previous!.isAuthenticated && next.isAuthenticated) { context.go('/home'); } else if (previous.isAuthenticated && !next.isAuthenticated) { context.go('/login'); } }); ``` ## Testing Helpers ```dart // Mock auth state final mockAuthState = AuthState.authenticated( UserEntity( userId: '123', username: 'test', accessToken: 'token', ), ); // Create test container final container = ProviderContainer( overrides: [ authProvider.overrideWith((ref) => MockAuthNotifier()), ], ); ``` ## Files Reference | Layer | File | Purpose | |-------|------|---------| | **Data** | `login_request_model.dart` | Request DTO | | | `user_model.dart` | User DTO | | | `auth_remote_datasource.dart` | API calls | | | `auth_repository_impl.dart` | Repository impl | | **Domain** | `user_entity.dart` | Domain entity | | | `auth_repository.dart` | Repository interface | | | `login_usecase.dart` | Business logic | | **Presentation** | `login_page.dart` | Login UI | | | `login_form.dart` | Form widget | | | `auth_provider.dart` | State management | | **DI** | `auth_dependency_injection.dart` | Providers setup | ## Troubleshooting Quick Fixes | Issue | Solution | |-------|----------| | Provider not found | Add `ProviderScope` to main.dart | | Navigation fails | Check router configuration | | Tokens not saved | Verify secure storage setup | | API calls fail | Check base URL in constants | | State not updating | Use `ConsumerWidget` | ## Performance Tips 1. Use `ref.read()` for one-time operations 2. Use `ref.watch()` for reactive updates 3. Use `ref.listen()` for side effects 4. Avoid rebuilding entire tree - scope providers 5. Use `select()` for partial state watching ## Security Checklist - [x] Tokens in secure storage - [x] Password fields obscured - [x] No logging of sensitive data - [x] Token auto-added to headers - [x] Token cleared on logout - [x] Input validation - [ ] HTTPS only (configure in production) - [ ] Token expiration handling - [ ] Rate limiting - [ ] Biometric auth (optional)