Files
Kordant/tasks/shieldai-unified-restructure/30-ios-auth-onboarding.md
2026-05-25 12:23:23 -04:00

6.0 KiB

30. iOS App — Authentication, Onboarding, and Account Setup

meta: id: shieldai-unified-restructure-30 feature: shieldai-unified-restructure priority: P1 depends_on: [shieldai-unified-restructure-28, shieldai-unified-restructure-29] tags: [ios, swiftui, auth, onboarding, mobile]

objective:

  • Build the authentication and onboarding flow for the iOS app: login, signup, password reset, and a multi-step onboarding experience. Use native iOS authentication where possible (Sign in with Apple) and maintain visual consistency with the web app.

deliverables:

  • iOS/ShieldAI/Views/Auth/AuthView.swift — Auth container:
    • Switches between login and signup modes
    • ShieldAI branding at top
    • Social auth buttons (Sign in with Apple, Google)
  • iOS/ShieldAI/Views/Auth/LoginView.swift — Login screen:
    • Email and password fields using ShieldTextField
    • "Remember me" toggle
    • "Forgot password?" link
    • "Sign In" ShieldButton
    • "Don't have an account? Sign up" link
  • iOS/ShieldAI/Views/Auth/SignupView.swift — Signup screen:
    • Name, email, password, confirm password fields
    • Password strength indicator
    • Terms of service agreement toggle
    • "Create Account" button
  • iOS/ShieldAI/Views/Auth/ForgotPasswordView.swift — Password reset:
    • Email input + submit
    • Success state with instructions
  • iOS/ShieldAI/Views/Onboarding/OnboardingView.swift — Onboarding flow:
    • Page-based TabView with 4 steps
    • Step 1: Welcome + plan selection (Basic, Plus, Premium cards)
    • Step 2: Add first watchlist item (email or phone)
    • Step 3: Invite family members (optional)
    • Step 4: Setup complete → transition to main app
  • iOS/ShieldAI/Views/Auth/BiometricAuthView.swift — Face ID / Touch ID prompt:
    • Triggered after first successful login
    • Uses LocalAuthentication framework
    • Stores preference in Keychain
  • iOS/ShieldAI/Services/AuthService.swift — Auth business logic:
    • login(email, password) → calls API (task 31)
    • signup(name, email, password) → calls API
    • resetPassword(email) → calls API
    • signInWithApple() → handles Apple ID credential
    • signInWithGoogle() → handles Google Sign-In
    • enableBiometricAuth() → stores credential in Keychain
    • logout() → clears tokens and Keychain

steps:

  1. Create iOS/ShieldAI/Views/Auth/ and iOS/ShieldAI/Views/Onboarding/ directories.
  2. AuthView:
    • Use @State to toggle between login and signup
    • Show ShieldAI logo and tagline at top
    • Use ShieldCard for the form container
  3. LoginView:
    • ShieldTextField for email and password
    • Toggle for "Remember me"
    • ShieldButton for submit
    • Link to ForgotPasswordView
    • On success: store JWT in Keychain, navigate to main app or onboarding
  4. SignupView:
    • Additional fields: name, confirm password
    • Password strength: check length, uppercase, number, special char
    • Visual strength bar using ShieldProgressBar
    • Terms toggle (required)
    • On success: store JWT, show onboarding
  5. ForgotPasswordView:
    • Simple email field + submit
    • Success message: "Check your email for reset instructions"
  6. OnboardingView:
    • TabView with .tabViewStyle(.page) for swipeable steps
    • Step 1: Plan cards with feature lists, highlight recommended tier
    • Step 2: Input for email/phone, "Add" button, shows added items list
    • Step 3: Email inputs for family invites, "Skip" button
    • Step 4: Success animation (checkmark), "Get Started" button
    • Progress dots at bottom showing current step
  7. BiometricAuthView:
    • LAContext for Face ID / Touch ID evaluation
    • On success: store "useBiometric" preference and credential in Keychain
    • On failure: fall back to password
  8. AuthService:
    • Protocol-based for testability
    • Implementation calls API client (task 31)
    • Keychain wrapper for secure token storage
    • Apple Sign-In: use AuthenticationServices framework (ASAuthorizationAppleIDButton)
    • Google Sign-In: use GoogleSignIn SDK
  9. Wire auth state to root view:
    • ContentView observes AuthService.isAuthenticated
    • On logout: clear state and show AuthView

steps:

  • Unit: AuthService stores and retrieves tokens from Keychain
  • Unit: Password strength calculator returns correct level
  • Unit: Onboarding stepper advances and collects data
  • Integration: Sign in with Apple button triggers ASAuthorizationController
  • E2E: Complete login → onboarding → main app flow

acceptance_criteria:

  • Login screen accepts email/password and authenticates via API
  • Signup screen validates inputs and creates account via API
  • Password reset flow sends request to API and shows success state
  • Onboarding has 4 steps with progress indicator and swipe navigation
  • Sign in with Apple button works and authenticates user
  • Biometric auth (Face ID/Touch ID) can be enabled after first login
  • Tokens are stored securely in iOS Keychain
  • Logout clears all auth state and returns to login screen
  • Auth flow matches web app visual style

validation:

  • Run app on simulator, complete login with test credentials
  • Verify JWT stored in Keychain (use Keychain utility or debug print)
  • Test Sign in with Apple flow (simulator supports mock Apple ID)
  • Complete onboarding and verify data sent to API
  • Test Face ID prompt on device (simulator can simulate with Features menu)
  • Run unit tests via Xcode Cmd+U

notes:

  • Sign in with Apple is required for App Store approval if you offer other third-party sign-in options.
  • Use ASAuthorizationController for Apple Sign-In. Handle both .signIn and .credentialRevokedNotification.
  • For Google Sign-In, the GoogleSignIn SDK requires a GoogleService-Info.plist. Add setup instructions to README.
  • Keychain token storage should use kSecAttrAccessibleWhenUnlockedThisDeviceOnly for security.
  • The onboarding data (plan, watchlist items, family invites) should be collected in a local model and submitted to the API at the final step (or incrementally).
  • Consider using SwiftUI's .fullScreenCover for the auth flow so it covers the entire screen without tab bar.