FirebaseUI for iOS

repository·main·Indexed 23 days ago

https://github.com/firebase/firebaseui-ios

Provides UI bindings for Firebase to connect UI elements to Firestore, Realtime Database, and Storage for real-time updates. Includes FUITableViewDataSource and FUICollectionViewDataSource for automatic data binding, FUIArray for synchronized data arrays, and modern SwiftUI components for simplified Firebase authentication via AuthPickerView and AuthService.

Tokens
12.5K
Snippets
36
Records
55
Agent score
82%

What's inside firebaseui-ios

  1. Use FUIArray for custom synchronized data arrays

    main

    If you are building a complex UI (such as a multi-section UI) that cannot be handled by the standard data sources, use FUIArray. FUIArray synchronizes a Firebase FIRDatabaseReference with a local array and surfaces Firebase events through the FUICollectionDelegate protocol. You can subclass FUIArray to implement custom behaviors like client-side sorting (e.g., using FUISortedArray).

    let firebaseRef = Database.database().reference()
    let array = FUIArray(query: firebaseRef)
  2. Initialize and use AuthService

    main

    The AuthService is the central object for managing authentication. You create it with an AuthConfiguration, register your desired sign-in methods using builder-style methods, and then pass it to your views via the .environment(authService) modifier.

    To use the opinionated default UI, wrap your content in an AuthPickerView and provide the AuthService in the environment.

    import FirebaseAuthSwiftUI
    import SwiftUI
    
    struct ContentView: View {
      let authService: AuthService
    
      init() {
        let configuration = AuthConfiguration()
    
        authService = AuthService(configuration: configuration)
          .withEmailSignIn()
      }
    
      var body: some View {
        AuthPickerView {
          // Your authenticated app content goes here.
          Text("Welcome to your app!")
        }
        .environment(authService)
      }
    }
  3. Handle reauthentication errors in custom views

    main

    When performing sensitive operations (like deleteUser(), updatePassword(), or unenrollMFA()), Firebase may require recent authentication. If it does, AuthService will throw an AuthServiceError containing a context object. You must catch this error and prompt the user to reauthenticate.

    Error Mapping

    • oauthReauthenticationRequired(context:): For OAuth providers. Use reauthenticate(context:) with the provided OAuthReauthContext.
    • emailReauthenticationRequired(context:): For Email/Password. Prompt for password, then call reauthenticate(with:) using the provided EmailReauthContext.
    • emailLinkReauthenticationRequired(context:): For Email Link. Use sendEmailSignInLink(email:isReauth:true) with the provided email, then handle the incoming link with handleSignInLink(url:).
    • phoneReauthenticationRequired(context:): For Phone. Handle SMS verification, then call reauthenticate(with:) using the provided PhoneReauthContext.
  4. Customize Authentication experience

    main

    You can customize the authentication experience at three levels:

    1. Behavioral Configuration: Use AuthConfiguration to set Terms of Service URLs, Privacy Policy URLs, custom localized strings, and MFA support.
    2. Layout Customization: Use authService.renderButtons() to get the built-in buttons to use in your own custom SwiftUI layout.
    3. Full Customization: Build your own views and call AuthService methods directly (e.g., signIn(email:password:), verifyPhoneNumber(_:), etc.), or register your own provider button by conforming to AuthProviderUI and calling authService.registerProvider(providerWithButton:).
    // Behavioral Configuration
    let configuration = AuthConfiguration(
      shouldAutoUpgradeAnonymousUsers: true,
      customStringsBundle: .main,
      tosUrl: URL(string: "https://example.com/terms"),
      privacyPolicyUrl: URL(string: "https://example.com/privacy"),
      mfaEnabled: true
    )
  5. Automatic Reauthentication in Default Views

    main

    When performing sensitive operations (e.g., deleting accounts, updating passwords), FirebaseUI for SwiftUI handles reauthentication automatically based on the provider:

    • OAuth Providers (Google, Apple, Facebook, Twitter, etc.): Displays an alert for confirmation, then automatically obtains fresh credentials.
    • Email/Password: Presents a sheet prompting the user to enter their password.
    • Email Link: Shows an alert to send a verification email, then a sheet with instructions to check email.
    • Phone: Shows an alert for verification, then a sheet for SMS code entry.

    The operation automatically retries after successful reauthentication without requiring additional code when using AuthPickerView or built-in account management views.

  6. How FirestoreUI diffing works

    main

    FirestoreUI uses FUIBatchedArray to transform Firestore query snapshot updates into array updates. These updates are described by FUISnapshotArrayDiff, which provides a format friendly to UITableView and UICollectionView animations.

    While FUISnapshotArrayDiff and its helpers are the core of the diffing logic, they are intended for internal use by the data sources. However, because the operations are pure and mostly independent of Firestore, you can use the functions provided in this class to diff arbitrary data in your own application.

  7. Use AuthPickerView for default authentication UI

    main

    The AuthPickerView is a pre-built, opinionated UI that manages the entire authentication flow, including navigation between sign-in, password recovery, MFA, and verification screens. It automatically switches between the authentication UI and your app content based on the authService.authenticationState.

    To use it, initialize an AuthService with your desired providers and wrap your authenticated content within the AuthPickerView closure. You can control the visibility of the authentication sheet using authService.isPresented.

    import FirebaseAuthSwiftUI
    import SwiftUI
    
    struct ContentView: View {
      let authService: AuthService
    
      init() {
        let configuration = AuthConfiguration()
        
        authService = AuthService(configuration: configuration)
          .withEmailSignIn()
      }
    
      var body: some View {
        AuthPickerView {
          // Your authenticated app content goes here
          Text("Welcome to your app!")
        }
        .environment(authService)
      }
    }
  8. Handle reauthentication for sensitive operations

    main

    When performing sensitive operations (like deleting a user or updating a password), Firebase may require reauthentication. You must catch the specific AuthServiceError and use the provided context to trigger the appropriate reauthentication flow.

    OAuth Providers (Google, Apple, etc.)

    Catch .oauthReauthenticationRequired(context) and call authService.reauthenticate(context:).

    Email/Password

    Catch .emailReauthenticationRequired(context), prompt the user for their password, create an EmailAuthProvider.credential, and call authService.reauthenticate(with:).

    Phone

    Catch .phoneReauthenticationRequired(context), verify the phone number via authService.verifyPhoneNumber(phoneNumber:), and call authService.reauthenticate(with:) using the resulting credential.

    Catch .emailLinkReauthenticationRequired(context), call authService.sendEmailSignInLink(email:isReauth:), and use authService.handleSignInLink(url:) when the user returns to the app.

    // Example: OAuth Reauthentication
    do {
      try await authService.deleteUser()
    } catch let error as AuthServiceError {
      if case .oauthReauthenticationRequired(let context) = error {
        try await authService.reauthenticate(context: context)
        try await authService.deleteUser() // Retry
      }
    }
  9. Install FirebaseUI for iOS via Swift Package Manager

    main

    Use Swift Package Manager (SPM) to access modern SwiftUI authentication components.

    1. In Xcode, go to File > Add Package Dependencies.
    2. Enter the repository URL: https://github.com/firebase/FirebaseUI-iOS.
    3. Select the specific modules required for your project:
    https://github.com/firebase/FirebaseUI-iOS
  10. Register Apple Sign-In

    main

    To use Sign in with Apple:

    1. Enable Apple in the Firebase console.
    2. Add the Sign in with Apple capability in Xcode.
    3. Follow the standard Firebase guide for Apple platforms.
    4. Register the provider using .withAppleSignIn().
     let authService = AuthService()
      .withAppleSignIn()
  11. Register Phone Number authentication

    main

    To use phone authentication:

    1. Enable Phone in the Firebase console.
    2. Configure APNs for your app and enable Push Notifications in Xcode.
    3. Add your Firebase Encoded App ID as a URL scheme for reCAPTCHA fallback.
    4. Register the provider using .withPhoneSignIn().
    5. Note: You must also implement APNs token and reCAPTCHA URL handling in your AppDelegate (see 'Handle provider callbacks').
     let authService = AuthService()
      .withPhoneSignIn()
  12. Register Email Link (Passwordless) authentication

    main

    To use passwordless email link sign-in:

    1. Enable Email link (passwordless sign-in) in the Firebase console.
    2. Add the link domain to Authorized domains.
    3. If building custom views, call authService.handleSignInLink(url:) when the link opens the app.
    4. Configure ActionCodeSettings with your app's URL and iOS Bundle ID, then pass it to AuthConfiguration.
    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.url = URL(string: "https://yourapp.firebaseapp.com")
    
    guard let bundleID = Bundle.main.bundleIdentifier else {
      fatalError("Missing bundle identifier for email link authentication setup.")
    }
    
    actionCodeSettings.setIOSBundleID(bundleID)
    
    let configuration = AuthConfiguration(
      emailLinkSignInActionCodeSettings: actionCodeSettings
    )
    
    let authService = AuthService(configuration: configuration)
      .withEmailLinkSignIn()