2.8 KiB
2.8 KiB
feature:auth
Screens
- ServerUrlScreen -- first-run server URL entry with validation and QR scan option
- LoginScreen -- email/password + social OAuth buttons + LDAP username mode
- RegisterScreen -- name, username, email, password, confirm password
- ForgotPasswordScreen -- email entry for password reset link
- TwoFactorScreen -- 6-digit OTP input with backup code fallback
Navigation
- Sealed interface:
AuthRoute : NavKeywith typed route classes - Routes:
ServerUrl,Login,Register,ForgotPassword,TwoFactor(tempToken),VerifyEmail(email),ResetPassword(userId, token),Terms(all@Serializable) - Feature entries registered via
EntryProviderScope<NavKey>.authEntries() - Flow:
ServerUrl→Login→ (2FA iftempTokenreturned) →onAuthComplete - Register and ForgotPassword are lateral routes from Login
TwoFactor(val tempToken: String)data class carries the nav argument directly
OAuth Flow
OAuthManageropens Chrome Custom Tabs to{serverUrl}/api/oauth/{provider}- On return (Activity.onResume),
CookieManager.getCookie()extractsrefreshToken=cookie - Cookie is cleared after extraction to prevent stale reads
- Supported providers configured by server: Google, GitHub, Discord, Facebook, Apple, OpenID
Token Storage
- Tokens stored in
EncryptedSharedPreferencesviaTokenDataStorein:core:data - Refresh token sent as Cookie header (backend reads
cookies.parse(req.headers.cookie)) - Access token sent as Bearer header
- Token refresh is an explicit POST, not automatic cookie-based
ViewModels
- One ViewModel per screen:
ServerUrlViewModel,LoginViewModel,RegisterViewModel,ForgotPasswordViewModel,TwoFactorViewModel - All use
AuthRepositoryfrom:core:data
Key Implementation Notes
- If server URL is already stored, skip ServerUrl screen on launch
- Social logins must use Custom Tabs, not WebView (cookie sharing requirement)
openidAutoRedirectfrom server config triggers automatic redirect instead of showing login form- LDAP mode: show "Username" field instead of "Email" (check server config)
Terms Screen
TermsScreen+TermsViewModel— displays server terms, "I Accept" button- Route:
Termsdata object (part ofAuthRoutesealed interface) inAuthNavigation.kt - Loads terms text via
UserRepository, posts acceptance on confirm TermsViewModel.consumeAccepted()resets navigation trigger- Gotcha: Terms check should happen after login if
startupConfig.requireTermsis true - Note:
VerifyEmailScreenalready existed pre-Round 2
Localization
strings.xmlcreated for all 8 modules (app, core/ui, feature/auth, chat, conversations, settings, agents, files)- Contains key toolbar titles, button labels, section headers — NOT exhaustive extraction
- Full string extraction is a future pass