diff --git a/.planning/phases/01-authentication/01-RESEARCH.md b/.planning/phases/01-authentication/01-RESEARCH.md new file mode 100644 index 0000000..3268f9b --- /dev/null +++ b/.planning/phases/01-authentication/01-RESEARCH.md @@ -0,0 +1,326 @@ +# Phase 1: Authentication & Account Basics - Research + +**Researched:** 2026-01-28 +**Domain:** Flutter + Supabase Authentication +**Confidence:** HIGH + +## Summary + +Sage requires Flutter-based authentication using Supabase as the backend service. The established pattern is to use the `supabase_flutter` package (v2.12.0) which provides comprehensive authentication capabilities including email/password signup, password reset, session persistence, and auth state management. The package handles session persistence using SharedPreferences by default, with optional secure storage support via FlutterSecureStorage for enhanced security. + +**Primary recommendation:** Use supabase_flutter v2.12.0 with default SharedPreferences storage and PKCE flow for secure authentication across Android and web platforms. + +## Standard Stack + +The established libraries/tools for this domain: + +### Core +| Library | Version | Purpose | Why Standard | +|---------|---------|---------|--------------| +| supabase_flutter | ^2.12.0 | Official Supabase client for Flutter | Provides complete auth implementation, session management, and real-time auth state updates | +| flutter_secure_storage | ^9.0.0 | Enhanced session security (optional) | Industry standard for storing sensitive data securely on mobile devices | +| shared_preferences | ^2.0.0 | Default session persistence | Built-in Supabase storage method, lightweight and reliable | + +### Supporting +| Library | Version | Purpose | When to Use | +|---------|---------|---------|-------------| +| go_router | ^13.0.0 | Navigation management | For handling auth-based routing and redirects | +| riverpod | ^2.5.0 | State management | For managing global auth state across the app | + +### Alternatives Considered +| Instead of | Could Use | Tradeoff | +|------------|-----------|----------| +| supabase_flutter | firebase_auth | Firebase would work but Supabase is already decided as project standard, better PostgreSQL integration | +| supabase_flutter | custom auth implementation | Custom auth is significantly more complex, security risks, requires implementing session management, password hashing, token refresh manually | + +**Installation:** +```bash +flutter pub add supabase_flutter flutter_secure_storage +``` + +## Architecture Patterns + +### Recommended Project Structure +``` +src/ +├── lib/ +│ ├── main.dart # Supabase initialization +│ ├── core/ +│ │ ├── constants/ +│ │ │ └── supabase_constants.dart # Supabase URL and keys +│ │ └── errors/ +│ │ └── auth_exceptions.dart # Custom auth error handling +│ ├── features/ +│ │ └── authentication/ +│ │ ├── data/ +│ │ │ └── models/ +│ │ │ └── auth_user.dart # User model +│ │ ├── domain/ +│ │ │ └── repositories/ +│ │ │ └── auth_repository.dart # Auth interface +│ │ └── presentation/ +│ │ ├── pages/ +│ │ │ ├── login_page.dart +│ │ │ ├── signup_page.dart +│ │ │ └── reset_password_page.dart +│ │ └── widgets/ +│ │ ├── auth_form.dart +│ │ └── auth_button.dart +│ └── providers/ +│ └── auth_provider.dart # Global auth state management +``` + +### Pattern 1: Supabase Initialization +**What:** Initialize Supabase at app startup with proper configuration +**When to use:** In main.dart before runApp() +**Example:** +```dart +// Source: https://pub.dev/packages/supabase_flutter +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + + await Supabase.initialize( + url: SUPABASE_URL, + anonKey: SUPABASE_ANON_KEY, + authOptions: FlutterAuthClientOptions( + localStorage: const SharedPreferencesLocalStorage(), // Default, secure enough + // For enhanced security on mobile: + // localStorage: MySecureStorage(), + ), + ); + + runApp(MyApp()); +} + +final supabase = Supabase.instance.client; +``` + +### Pattern 2: Auth State Management +**What:** Use StreamBuilder or Riverpod to listen to auth state changes +**When to use:** Throughout the app for UI updates based on auth state +**Example:** +```dart +// Source: https://supabase.com/docs/reference/dart/auth-onauthstatechange +class AuthProvider extends ChangeNotifier { + User? _user; + User? get user => _user; + + AuthProvider() { + supabase.auth.onAuthStateChange.listen((data) { + final AuthChangeEvent event = data.event; + final Session? session = data.session; + + _user = session?.user; + notifyListeners(); + }); + } +} +``` + +### Pattern 3: Authentication Methods +**What:** Use Supabase auth methods for signup, login, password reset +**When to use:** For all auth operations +**Example:** +```dart +// Email signup +final AuthResponse res = await supabase.auth.signUp( + email: email, + password: password, +); + +// Email login +final AuthResponse res = await supabase.auth.signInWithPassword( + email: email, + password: password, +); + +// Password reset +await supabase.auth.resetPasswordForEmail( + email, + redirectTo: 'http://example.com/account/update-password', +); +``` + +### Anti-Patterns to Avoid +- **Manual token management:** Don't store JWT tokens manually or implement custom refresh logic +- **Ignoring auth state:** Don't skip onAuthStateChange listener - leads to UI inconsistencies +- **Hardcoded credentials:** Never store Supabase keys directly in code - use environment variables + +## Don't Hand-Roll + +Problems that look simple but have existing solutions: + +| Problem | Don't Build | Use Instead | Why | +|---------|-------------|-------------|-----| +| Session persistence | Custom token storage with SharedPreferences | Supabase built-in session management | Handles token expiration, refresh, security automatically | +| Password reset email flow | Custom SMTP + email templates | Supabase resetPasswordForEmail() | Built-in rate limiting, secure token generation, proper email handling | +| Auth state management | Manual user state with setState() | onAuthStateChange stream | Automatic updates across all app components | +| Error handling | Try-catch for every auth call | AuthException handling | Consistent error messages, proper user feedback | + +**Key insight:** Supabase handles all security-critical aspects like token refresh, session validation, and password reset flow securely. Custom implementations risk security vulnerabilities. + +## Common Pitfalls + +### Pitfall 1: Session Not Persisting +**What goes wrong:** User gets logged out when app restarts +**Why it happens:** Missing localStorage configuration or using EmptyLocalStorage +**How to avoid:** Ensure proper initialization with default localStorage +**Warning signs:** User must log in every time app launches + +### Pitfall 2: Auth State Not Updating UI +**What goes wrong:** UI doesn't reflect login/logout status +**Why it happens:** Not listening to onAuthStateChange events +**How to avoid:** Always subscribe to auth state changes in app initialization +**Warning signs:** User stuck on login screen after successful authentication + +### Pitfall 3: Password Reset Flow Fails +**What goes wrong:** Reset links don't work or redirect incorrectly +**Why it happens:** Missing redirect URL configuration in Supabase dashboard +**How to avoid:** Configure redirect URLs in Authentication > URL Configuration +**Warning signs:** Users report broken password reset emails + +### Pitfall 4: Web Service Worker Issues +**What goes wrong:** Flutter web app fails to register service worker +**Why it happens:** Improper web hosting configuration for password reset callback +**How to avoid:** Ensure web server serves correct MIME types for service workers +**Warning signs:** Console errors about service worker MIME types + +### Pitfall 5: Environment Variable Exposure +**What goes wrong:** Supabase keys exposed in client code +**Why it happens:** Hardcoding values instead of using environment variables +**How to avoid:** Use flutter_dotenv for local dev, proper CI/CD secrets for production +**Warning signs:** Keys visible in compiled code or version control + +## Code Examples + +Verified patterns from official sources: + +### Email Sign Up +```dart +// Source: https://supabase.com/docs/reference/dart/auth-signup +final AuthResponse res = await supabase.auth.signUp( + email: 'example@email.com', + password: 'example-password', +); +final Session? session = res.session; +final User? user = res.user; +``` + +### Email Sign In +```dart +// Source: https://supabase.com/docs/reference/dart/auth-signinwithpassword +final AuthResponse res = await supabase.auth.signInWithPassword( + email: 'example@email.com', + password: 'example-password', +); +final Session? session = res.session; +final User? user = res.user; +``` + +### Password Reset +```dart +// Source: https://supabase.com/docs/guides/auth/passwords +await supabase.auth.resetPasswordForEmail( + 'valid.email@supabase.io', + redirectTo: 'http://example.com/account/update-password', +); +``` + +### Auth State Listening +```dart +// Source: https://supabase.com/docs/reference/dart/auth-onauthstatechange +final authSubscription = supabase.auth.onAuthStateChange.listen((data) { + final AuthChangeEvent event = data.event; + final Session? session = data.session; + + switch (event) { + case AuthChangeEvent.signedIn: + // Navigate to home + break; + case AuthChangeEvent.signedOut: + // Navigate to login + break; + } +}); +``` + +### Secure Storage Option +```dart +// Source: https://pub.dev/packages/supabase_flutter +class MySecureStorage extends LocalStorage { + final storage = FlutterSecureStorage(); + + @override + Future initialize() async {} + + @override + Future accessToken() async { + return storage.read(key: supabasePersistSessionKey); + } + + @override + Future persistSession(String persistSessionString) async { + return storage.write(key: supabasePersistSessionKey, value: persistSessionString); + } + + @override + Future removePersistedSession() async { + return storage.delete(key: supabasePersistSessionKey); + } +} +``` + +## State of the Art + +| Old Approach | Current Approach | When Changed | Impact | +|--------------|-----------------|--------------|--------| +| Hive-based storage (v1) | SharedPreferences-based storage (v2) | v2.0 release | Simpler, faster app startup, better platform support | +| Implicit auth flow | PKCE flow (default in v2) | v2.0 release | More secure for deep links and OAuth | +| Manual token refresh | Automatic token refresh | v1.x | Session persistence handled automatically | +| SupabaseAuth class | Direct client access | v2.0 release | Cleaner API, no wrapper classes needed | + +**Deprecated/outdated:** +- **SupabaseAuth.initialSession**: Use supabase.auth.currentSession instead +- **Hive storage**: Replaced with SharedPreferences in v2 +- **signInWithApple() method**: Removed from core package, use separate sign_in_with_apple package +- **Provider enum**: Renamed to OAuthProvider to avoid conflicts + +## Open Questions + +1. **Enhanced Security Requirements** + - What we know: FlutterSecureStorage available for enhanced session security + - What's unclear: Does Sage require enhanced security for food inventory app sensitivity? + - Recommendation: Use SharedPreferences for v1, evaluate FlutterSecureStorage for production + +2. **Email Template Customization** + - What we know: Supabase provides default email templates + - What's unclear: Does Sage need custom branding for password reset emails? + - Recommendation: Use default templates for v1, customize after user feedback + +3. **Rate Limiting Strategy** + - What we know: Supabase has built-in rate limiting (2 emails/hour default) + - What's unclear: Are these limits sufficient for household app usage patterns? + - Recommendation: Monitor and configure custom SMTP if limits are reached + +## Sources + +### Primary (HIGH confidence) +- supabase_flutter v2.12.0 documentation - Authentication methods, session management, initialization patterns +- Supabase official docs - Password reset flow, email authentication best practices + +### Secondary (MEDIUM confidence) +- Flutter Secure Storage package documentation - Enhanced session persistence options +- Medium articles on Flutter auth patterns - Real-world implementation patterns (verified with official docs) + +### Tertiary (LOW confidence) +- Stack Overflow discussions on specific error scenarios - Limited verification, use with caution + +## Metadata + +**Confidence breakdown:** +- Standard stack: HIGH - Based on official Supabase Flutter package documentation +- Architecture: HIGH - Verified with multiple official sources and community patterns +- Pitfalls: HIGH - Official documentation clearly documents common issues and solutions + +**Research date:** 2026-01-28 +**Valid until:** 2026-02-27 (30 days for stable authentication libraries) \ No newline at end of file