Librechat-Mobile/feature/auth/CLAUDE.md

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 : NavKey with 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: ServerUrlLogin → (2FA if tempToken returned) → onAuthComplete
  • Register and ForgotPassword are lateral routes from Login
  • TwoFactor(val tempToken: String) data class carries the nav argument directly

OAuth Flow

  • OAuthManager opens Chrome Custom Tabs to {serverUrl}/api/oauth/{provider}
  • On return (Activity.onResume), CookieManager.getCookie() extracts refreshToken= 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 EncryptedSharedPreferences via TokenDataStore in :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 AuthRepository from :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)
  • openidAutoRedirect from 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: Terms data object (part of AuthRoute sealed interface) in AuthNavigation.kt
  • Loads terms text via UserRepository, posts acceptance on confirm
  • TermsViewModel.consumeAccepted() resets navigation trigger
  • Gotcha: Terms check should happen after login if startupConfig.requireTerms is true
  • Note: VerifyEmailScreen already existed pre-Round 2

Localization

  • strings.xml created 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