Anmeldung mit FirebaseUI in Ihre iOS-App einfügen

FirebaseUI für SwiftUI ist eine moderne, auf SwiftUI ausgerichtete Bibliothek, die auf Firebase Authentication basiert und vordefinierte Anmeldeabläufe für Ihre App bietet.

FirebaseUI für SwiftUI bietet folgende Vorteile:

  • Vorgegebene Standard-UI: Fügen Sie mit AuthPickerView einen vollständigen Anmeldevorgang hinzu.
  • Anpassbar: Sie können die Standardschaltflächen in Ihrem eigenen Layout rendern oder eine vollständig benutzerdefinierte Oberfläche erstellen.
  • Anonyme Kontoverknüpfung: Sie können anonyme Nutzer optional upgraden, anstatt sie zu ersetzen.
  • Kontoverwaltung: Integrierte Abläufe für die Registrierung, Passwortwiederherstellung und Kontoverwaltung.
  • Mehrere Anbieter: E-Mail-Adresse/Passwort, E-Mail-Link, Telefonauthentifizierung, Apple, Google, Facebook, Twitter und Standard-OAuth2/OIDC-Anbieter.
  • Moderne Authentifizierungsfunktionen: Integrierte Unterstützung für Multi-Faktor-Authentifizierung (MFA) und asynchrone/Await-APIs.

Hinweis

Installation

FirebaseUI for SwiftUI wird als Swift-Paket bereitgestellt. So installieren Sie das Paket in Ihrem Xcode-Projekt:

  1. Klicken Sie in Xcode auf File > Add Package Dependencies.

  2. Geben Sie die Paket-URL ein:

    https://github.com/firebase/FirebaseUI-iOS
    
  3. Wählen Sie im Menü Abhängigkeitsregel die Option Bis zur nächsten Hauptversion aus und legen Sie die Mindestversion auf den neuesten Release fest.

  4. Klicken Sie auf Add Package (Paket hinzufügen) und wählen Sie die Bibliotheken aus, die Sie Ihrem Projekt hinzufügen möchten.

    Die folgende Bibliothek ist immer erforderlich. Es enthält die wichtigsten Abhängigkeiten sowie Unterstützung für die Anmeldung mit E‑Mail-Adresse und Passwort und die Anmeldung über einen E‑Mail-Link.

    • FirebaseAuthSwiftUI

     Wenn Sie andere Anmeldemethoden unterstützen möchten, wählen Sie auch eine oder mehrere der folgenden Bibliotheken aus:

    • FirebaseAppleSwiftUI (Über Apple anmelden)
    • FirebaseGoogleSwiftUI (Über Google anmelden)
    • FirebaseFacebookSwiftUI (Mit Facebook anmelden)
    • FirebasePhoneAuthSwiftUI (Telefonauthentifizierung)
    • FirebaseTwitterSwiftUI (Über Twitter anmelden)
    • FirebaseOAuthSwiftUI (Standard-OAuth- und OIDC-Anbieter wie GitHub, Microsoft, Yahoo)
  5. Klicken Sie auf Add Package (Paket hinzufügen), um die ausgewählten Bibliotheken zu installieren.

  6. Konfigurieren Sie den AuthService von FirebaseUI im Initialisierer Ihrer übergeordneten View und übergeben Sie den Dienst mithilfe der Umgebung an untergeordnete Ansichten.

    import FirebaseAuthSwiftUI
    import SwiftUI
    
    struct ContentView: View {
      let authService: AuthService
    
      init() {
        let configuration = AuthConfiguration()
    
        authService = AuthService(configuration: configuration)
          .withEmailSignIn() // Or whatever sign-in methods you want to support.
                             // See the next section.
      }
    
      var body: some View {
        AuthPickerView { // AuthPickerView (the prebuilt View) or a custom View.
            Text("Welcome to your app!")
        }
        .environment(authService)
      }
    }
    

Anmeldemethoden einrichten

Für jede der unterstützten Anmeldemethoden sind zusätzliche Einrichtungsschritte erforderlich. Maximieren Sie die Abschnitte unten und folgen Sie der Anleitung, um einzelne Anbieter einzurichten.

E‑Mail-Adresse und Passwort

  1. Aktivieren Sie im Abschnitt Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole den Anbieter E-Mail/Passwort.

  2. Registrieren Sie den Anbieter in Ihrer AuthService-Instanz:

    let authService = AuthService()
      .withEmailSignIn()
    

So verwenden Sie die Anmeldung ohne Passwort über einen E‑Mail-Link:

  1. Aktivieren Sie im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole die Option E-Mail/Passwort und dann die Anmeldung per E-Mail-Link. Beachten Sie, dass die Anmeldung per E-Mail oder Passwort aktiviert sein muss, um die Anmeldung per E-Mail-Link zu verwenden.

  2. Fügen Sie die Link-Domain zu Autorisierte Domains hinzu.

  3. Konfigurieren Sie ActionCodeSettings, übergeben Sie es an AuthConfiguration und registrieren Sie den Anbieter:

    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()
    
  4. Fügen Sie in derselben AppDelegate, in der Sie FirebaseApp.configure() aufrufen, der Methode application(_:open:options:) Logik hinzu, die true zurückgibt, wenn die geöffnete URL ein Firebase Authentication-Anmeldelink ist. Diese Logik gibt an, dass der Link von FirebaseUI verarbeitet wurde und nicht von anderen Link-Handlern verarbeitet werden sollte.

    import FacebookCore
    import FirebaseAuth
    import UIKit
    
    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        FirebaseApp.configure()
        return true
      }
    
      func application(
        _ application: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey: Any] = [:]
      ) -> Bool {
        if Auth.auth().canHandle(url) {
          return true
        }
        return false
      }
    }
    
  5. Wenn Sie benutzerdefinierte Ansichten erstellen, rufen Sie authService.handleSignInLink(url:) auf, wenn der Link Ihre App öffnet.

Apple

So verwenden Sie „Über Apple anmelden“:

  1. Konfigurieren Sie „Über Apple anmelden“:

    1. Aktivieren Sie „Über Apple anmelden“ für Ihre App auf der Seite Certificates, Identifiers & Profiles (Zertifikate, Kennungen und Profile) der Apple-Entwicklerwebsite.
    2. Verknüpfen Sie Ihre Website mit Ihrer App, wie im ersten Abschnitt von Configure Sign In with Apple for the web beschrieben. Registrieren Sie die folgende URL als Rückgabe-URL, wenn Sie dazu aufgefordert werden:
      https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
      Sie finden Ihre Firebase-Projekt-ID auf der Seite mit den Firebase-Console-Einstellungen. Notieren Sie sich anschließend die neue Dienst-ID, die Sie im nächsten Abschnitt benötigen.
    3. Erstellen Sie einen privaten Schlüssel für "Mit Apple anmelden". Sie benötigen Ihren neuen privaten Schlüssel und die Schlüssel-ID im nächsten Abschnitt.
    4. Wenn Sie Funktionen von Firebase Authentication verwenden, die E‑Mails an Nutzer senden, z. B. die Anmeldung über einen E‑Mail-Link, die Bestätigung von E‑Mail-Adressen oder die Aufhebung von Kontoänderungen, konfigurieren Sie den privaten E‑Mail-Relay-Dienst von Apple und registrieren Sie noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (oder Ihre benutzerdefinierte E‑Mail-Vorlagendomain), damit Apple von Firebase Authentication gesendete E‑Mails an anonymisierte Apple-E‑Mail-Adressen weiterleiten kann.
  2. Aktivieren Sie im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole die Option Apple.

    • Geben Sie die Dienst-ID an, die Sie im vorherigen Abschnitt erstellt haben.
    • Geben Sie im Abschnitt OAuth-Codeflusskonfiguration Ihre Apple-Team-ID sowie den privaten Schlüssel und die Schlüssel-ID an, die Sie im vorherigen Abschnitt erstellt haben.
  3. Öffnen Sie in Xcode den Bereich Signing & Capabilities (Signierung und Funktionen) des Projekteditors und fügen Sie die Funktion Sign in with Apple (Mit Apple anmelden) hinzu.

  4. Registrieren Sie den Anbieter in Ihrer AuthService-Instanz:

    let authService = AuthService()
      .withAppleSignIn()
    

Google

So verwenden Sie Google Log-in:

  1. Aktivieren Sie im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole den Anbieter Google.

  2. Laden Sie eine neue Kopie der GoogleService-Info.plist-Datei Ihres Projekts herunter und kopieren Sie sie in Ihr Xcode-Projekt. Alle vorhandenen Versionen werden durch die neue Version überschrieben.

  3. Fügen Sie Ihrem Xcode-Projekt benutzerdefinierte URL-Schemas hinzu:

    1. Öffnen Sie die Projektkonfiguration: Klicken Sie in der linken Strukturansicht auf den Projektnamen. Wählen Sie im Bereich TARGETS Ihre App aus, wählen Sie dann den Tab Info aus und maximieren Sie den Bereich URL Types.

    2. Klicken Sie auf den Button + und fügen Sie ein URL-Schema für Ihre umgekehrte Client-ID hinzu. Öffnen Sie die Konfigurationsdatei GoogleService-Info.plist und suchen Sie nach dem Schlüssel REVERSED_CLIENT_ID, um diesen Wert zu finden. Kopieren Sie den Wert dieses Schlüssels und fügen Sie ihn auf der Konfigurationsseite in das Feld URL-Schemas ein. Lassen Sie die anderen Felder unverändert.

      Wenn Sie fertig sind, sollte Ihre Konfiguration in etwa so aussehen (aber mit Ihren anwendungsspezifischen Werten):

  4. Registrieren Sie den Anbieter in Ihrer AuthService-Instanz:

    let authService = AuthService()
      .withGoogleSignIn()
    

Facebook

So verwenden Sie Facebook Login:

  1. Richten Sie das Facebook Login for iOS SDK ein. Folgen Sie dazu der Anleitung auf der Meta for Developers-Website. Überspringen Sie den letzten Schritt „Facebook-Anmeldung zu Ihrem Code hinzufügen“.

  2. Aktivieren Sie im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole den Anbieter Facebook. Sie benötigen die Facebook-App-ID und das App-Secret von der Meta for Developers-Website.

  3. Registrieren Sie den Anbieter in Ihrer AuthService-Instanz:

    let authService = AuthService()
     .withFacebookSignIn()
    

Telefonnummer

So verwenden Sie die Telefonauthentifizierung:

  1. Aktivieren Sie im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole den Anbieter Telefon.

  2. Konfigurieren Sie APNs für Ihre App wie im Abschnitt Lautlose Benachrichtigungen empfangen beschrieben.

  3. Fügen Sie Ihrem Xcode-Projekt benutzerdefinierte URL-Schemas hinzu:

    1. Öffnen Sie die Projektkonfiguration: Klicken Sie in der linken Strukturansicht auf den Projektnamen. Wählen Sie im Bereich TARGETS Ihre App aus, wählen Sie dann den Tab Info aus und maximieren Sie den Bereich URL Types.

    2. Klicken Sie auf das Pluszeichen (+) und fügen Sie die codierte App-ID als URL-Schema hinzu. Diesen Wert finden Sie in der Firebase-Konsole unter Einstellungen > Allgemein.

      Wenn Sie fertig sind, sollte Ihre Konfiguration in etwa so aussehen (aber mit Ihren anwendungsspezifischen Werten):

  4. Fügen Sie in derselben AppDelegate, in der Sie FirebaseApp.configure() aufrufen, APNs-Token-Handler hinzu:

    import FacebookCore
    import FirebaseAuth
    import UIKit
    
    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        FirebaseApp.configure()
        return true
      }
    
      func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
      ) {
        #if DEBUG
        Auth.auth().setAPNSToken(deviceToken, type: .sandbox)
        #else
        Auth.auth().setAPNSToken(deviceToken, type: .prod)
        #endif
      }
    }
    
  5. Registrieren Sie den Anbieter in Ihrer AuthService-Instanz:

    let authService = AuthService()
      .withPhoneSignIn()
    

Twitter (X)

So verwenden Sie die Twitter-Anmeldung:

  1. Generieren Sie X-API-Anmeldedaten, indem Sie der Anleitung auf der X-Entwicklerwebsite folgen.

  2. Aktivieren Sie im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole den Anbieter Twitter. Sie benötigen den API-Schlüssel und das API-Secret aus der X-Entwicklerkonsole.

  3. Registrieren Sie den Anbieter in Ihrer AuthService-Instanz:

    let authService = AuthService()
      .withTwitterSignIn()
    

Standard-OAuth2- und OIDC-Anbieter

FirebaseUI unterstützt auch integrierte OAuth-Anbieter wie GitHub, Microsoft und Yahoo sowie benutzerdefinierte OIDC-Anbieter, die in Firebase Authentication konfiguriert sind.

 let authService = AuthService()
  .withOAuthSignIn(OAuthProviderSwift.github())
  .withOAuthSignIn(OAuthProviderSwift.microsoft())
  .withOAuthSignIn(OAuthProviderSwift.yahoo())

Konfigurieren Sie benutzerdefinierte OIDC-Anbieter zuerst in Firebase Authentication und erstellen Sie dann ein OAuthProviderSwift mit Ihrer Anbieter-ID und der Schaltflächenkonfiguration:

let lineProvider = OAuthProviderSwift(
  providerId: "oidc.line",
  buttonLabel: "Sign in with LINE",
  displayName: "LINE",
  iconSystemName: "person.crop.circle.badge.checkmark",
  buttonBackgroundColor: .green,
  buttonForegroundColor: .white
)

let authService = AuthService()
  .withOAuthSignIn(lineProvider)

Vordefinierte Authentifizierungsansicht verwenden

FirebaseUI für SwiftUI bietet AuthPickerView, eine vordefinierte, optimierte Authentifizierungs-UI, die den gesamten Authentifizierungsablauf für Sie übernimmt. Dies ist die einfachste Möglichkeit, Ihrer Anwendung eine Authentifizierung hinzuzufügen.

Beispiel

Hier ein Beispiel für die Verwendung von AuthPickerView mit mehreren Anbietern und Konfigurationsoptionen:

import FirebaseAppleSwiftUI
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import SwiftUI

struct ContentView: View {
  let authService: AuthService

  init() {
    // Create configuration with options
    let configuration = AuthConfiguration(
      tosUrl: URL(string: "https://example.com/tos"),
      privacyPolicyUrl: URL(string: "https://example.com/privacy"),
      shouldAutoUpgradeAnonymousUsers: true
    )

    // Initialize AuthService with multiple providers
    authService = AuthService(configuration: configuration)
      .withEmailSignIn()
      .withAppleSignIn()
      .withGoogleSignIn()
  }

  var body: some View {
    AuthPickerView {
      authenticatedContent
    }
    .environment(authService)
  }

  var authenticatedContent: some View {
    NavigationStack {
      VStack(spacing: 20) {
        if authService.authenticationState == .authenticated {
          Text("Authenticated")
          
          Button("Manage Account") {
            authService.isPresented = true
          }
          .buttonStyle(.bordered)
          
          Button("Sign Out") {
            Task {
              try? await authService.signOut()
            }
          }
          .buttonStyle(.borderedProminent)
        } else {
          Text("Not Authenticated")
          
          Button("Sign In") {
            authService.isPresented = true
          }
          .buttonStyle(.borderedProminent)
        }
      }
      .navigationTitle("My App")
    }
    .onChange(of: authService.authenticationState) { _, newValue in
      // Automatically show auth UI when not authenticated
      if newValue != .authenticating {
        authService.isPresented = (newValue == .unauthenticated)
      }
    }
  }
}

Typische Anpassung

Alle AuthConfiguration-Parameter sind optional, aber die meisten Apps passen mindestens die folgenden Einstellungen an:

let configuration = AuthConfiguration(
    logo: ImageResource.exampleLogoAsset,
    customStringsBundle: .main,
    tosUrl: URL(string: "https://example.com/tos"),
    privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
  • logo: Das Logobild, das auf dem Authentifizierungsblatt angezeigt wird. Informationen zum Einbinden eines eigenen Bild-Assets finden Sie unter Bilder zu Ihrem Xcode-Projekt hinzufügen.

  • customStringsBundle: Benutzerdefinierte Strings aus dem angegebenen Bundle verwenden. Dies wird für die Lokalisierung, aber auch für die Anpassung der von AuthPickerView verwendeten Standardstrings verwendet. Wenn Sie beispielsweise die Nachricht festlegen möchten, die oben auf dem Authentifizierungsblatt angezeigt wird, erstellen Sie Localizable.strings mit folgendem Inhalt:

    "Sign in with Firebase" = "Sign in to use ExampleApp";
    

Inhalt der vordefinierten Ansicht

Wenn Sie AuthPickerView verwenden, erhalten Sie Folgendes:

  1. Sheet Presentation: Die Authentifizierungs-UI wird als modales Sheet angezeigt.
  2. Integrierte Navigation: Automatische Navigation zwischen den Bildschirmen für Anmeldung, Passwortwiederherstellung, MFA, E‑Mail-Link und Bestätigung der Telefonnummer
  3. Verwaltung des Authentifizierungsstatus: Wechselt automatisch zwischen der Authentifizierungs-UI und Ihren Inhalten basierend auf authService.authenticationState
  4. Steuerung über isPresented: Sie können festlegen, wann das Authentifizierungsblatt angezeigt wird, indem Sie authService.isPresented = true/false festlegen.

Fundierte Verhaltensweisen

Die Standard-AuthPickerView ist darauf ausgelegt, mehrere komplexe Szenarien zu verarbeiten:

1. Kontokonflikte beheben

Wenn ein Kontokonflikt auftritt (z.B. bei der Anmeldung mit Anmeldedaten, die bereits mit einem anderen Konto verknüpft sind), wird er von AuthPickerView automatisch behoben:

  • Konflikte bei anonymen Upgrades: Wenn shouldAutoUpgradeAnonymousUsers aktiviert ist und während eines anonymen Upgrades ein Konflikt auftritt, meldet das System den anonymen Nutzer automatisch ab und mit den neuen Anmeldedaten an.
  • Andere Konflikte: Bei Konflikten zwischen nicht anonymen Konten speichert das System die ausstehenden Anmeldedaten und versucht, sie nach erfolgreicher Anmeldung zu verknüpfen.

Dies wird durch den AccountConflictModifier übernommen, der auf NavigationStack-Ebene angewendet wird.

2. Multi-Faktor-Authentifizierung (MFA)

Wenn die MFA in Ihrer Konfiguration aktiviert ist:

  • Automatische Erkennung, wenn bei der Anmeldung eine MFA erforderlich ist
  • Zeigt entsprechende MFA-Auflösungsbildschirme (SMS oder TOTP) an.
  • Verarbeitet die Abläufe für die MFA-Registrierung und -Verwaltung
  • Unterstützt sowohl SMS-basierte als auch zeitbasierte Einmalpasswörter (TOTP)
3. Fehlerbehandlung

Die Standardansichten enthalten eine integrierte Fehlerbehandlung:

  • Zeigt nutzerfreundliche Fehlermeldungen in Benachrichtigungsdialogen an
  • Filtert automatisch Fehler heraus, die intern behandelt werden (z.B. Abbruchfehler, automatisch behandelte Konflikte)
  • Verwendet lokalisierte Fehlermeldungen über StringUtils
  • Fehler werden über den Umgebungsschlüssel reportError weitergegeben.

Wenn die Anmeldung per E-Mail-Link konfiguriert ist:

  • Die E-Mail-Adresse wird automatisch im App-Speicher gespeichert.
  • Verarbeitet die Deeplink-Navigation aus E-Mails
  • Verwaltet den gesamten Ablauf der E‑Mail-Bestätigung
  • Unterstützt Upgrades für anonyme Nutzer über einen E‑Mail-Link
5. Automatisches Upgrade für anonyme Nutzer

Wenn shouldAutoUpgradeAnonymousUsers aktiviert ist, gilt Folgendes:

  • Versucht automatisch, anonyme Konten mit neuen Anmeldedaten zu verknüpfen
  • Nutzerdaten werden beibehalten, indem anonyme Sitzungen aktualisiert statt ersetzt werden.
  • Behandelt Upgrade-Konflikte auf angemessene Weise.
6. Erneute Authentifizierung in Standardansichten

Für sensible Vorgänge wie das Löschen von Konten, das Aktualisieren von Passwörtern oder das Abmelden von MFA-Faktoren ist eine aktuelle Authentifizierung erforderlich. Wenn Sie Standardansichten verwenden, wird die erneute Authentifizierung automatisch basierend auf dem Anmeldeanbieter des Nutzers durchgeführt.

Wenn für einen sensiblen Vorgang eine erneute Authentifizierung erforderlich ist, werden in den Standardansichten automatisch folgende Schritte ausgeführt:

  • OAuth-Anbieter (Google, Apple, Facebook, Twitter usw.): Eine Benachrichtigung anzeigen, in der der Nutzer zur Bestätigung aufgefordert wird, dann automatisch neue Anmeldedaten abrufen und den Vorgang abschließen.

  • E-Mail-Adresse/Passwort: Es wird ein Fenster angezeigt, in dem der Nutzer aufgefordert wird, sein Passwort einzugeben, bevor er fortfahren kann.

  • E‑Mail-Link: Es wird eine Benachrichtigung angezeigt, in der der Nutzer gefragt wird, ob eine Bestätigungs-E‑Mail gesendet werden soll. Anschließend wird ein Fenster mit einer Anleitung zum Prüfen der E‑Mails angezeigt. Der Nutzer tippt auf den Link in der E‑Mail, um die erneute Authentifizierung abzuschließen.

  • Smartphone: Es wird eine Benachrichtigung angezeigt, in der erklärt wird, dass eine Bestätigung erforderlich ist. Anschließend wird ein Formular für die Bestätigung per SMS-Code angezeigt.

Der Vorgang wird nach erfolgreicher erneuter Authentifizierung automatisch wiederholt. Wenn Sie AuthPickerView oder die integrierten Ansichten zur Kontoverwaltung (UpdatePasswordView, SignedInView usw.) verwenden, ist kein zusätzlicher Code erforderlich.

Erweitert: Benutzerdefinierte Authentifizierungsansichten erstellen

Wenn Sie mehr Kontrolle über die Benutzeroberfläche oder den Navigationsablauf benötigen, können Sie eigene benutzerdefinierte Authentifizierungsansichten erstellen und trotzdem das AuthService für die Authentifizierungslogik verwenden.

Sie können Elemente von FirebaseUI auf vielfältige Weise mit benutzerdefinierter Logik kombinieren. Die folgenden Abschnitte enthalten Beispiele für einige der Anpassungsansätze, die Sie verwenden können.

Ansatz 1: Benutzerdefinierte Schaltflächen mit registerProvider()

Wenn Sie die vollständige Kontrolle über das Erscheinungsbild der Schaltfläche haben möchten, können Sie eine eigene benutzerdefinierte AuthProviderUI-Implementierung erstellen, die einen beliebigen Anbieter umschließt und Ihre benutzerdefinierte Schaltflächenansicht zurückgibt.

Benutzerdefinierte Anbieter-UI erstellen

Hier ein Beispiel für die Erstellung einer benutzerdefinierten Twitter-Schaltfläche:

import FirebaseAuthSwiftUI
import FirebaseTwitterSwiftUI
import SwiftUI

// Step 1: Create your custom button view
struct CustomTwitterButton: View {
  let provider: TwitterProviderSwift
  @Environment(AuthService.self) private var authService
  @Environment(\.mfaHandler) private var mfaHandler

  var body: some View {
    Button {
      Task {
        do {
          let outcome = try await authService.signIn(provider)

          // Handle MFA if required
          if case let .mfaRequired(mfaInfo) = outcome,
             let onMFA = mfaHandler {
            onMFA(mfaInfo)
          }
        } catch {
          // Do Something Else
        }
      }
    } label: {
      HStack { // Your custom icon
        Text("Sign in with Twitter")
          .fontWeight(.semibold)
      }
      .frame(maxWidth: .infinity)
      .padding()
      .background(
        LinearGradient(
          colors: [Color.blue, Color.cyan],
          startPoint: .leading,
          endPoint: .trailing
        )
      )
      .foregroundColor(.white)
      .cornerRadius(12)
      .shadow(radius: 4)
    }
  }
}

// Step 2: Create a custom AuthProviderUI wrapper
class CustomTwitterProviderAuthUI: AuthProviderUI {
  private let typedProvider: TwitterProviderSwift
  var provider: AuthProviderSwift { typedProvider }
  let id: String = "twitter.com"

  init(provider: TwitterProviderSwift = TwitterProviderSwift()) {
    typedProvider = provider
  }

  @MainActor func authButton() -> AnyView {
    AnyView(CustomTwitterButton(provider: typedProvider))
  }
}

// Step 3: Use it in your app
struct ContentView: View {
  let authService: AuthService

  init() {
    let configuration = AuthConfiguration()
    authService = AuthService(configuration: configuration)

    // Register your custom provider UI
    authService.registerProvider(
      providerWithButton: CustomTwitterProviderAuthUI()
    )
    authService.isPresented = true
  }

  var body: some View {
    AuthPickerView {
      usersApp
    }
    .environment(authService)
  }

  var usersApp: some View {
    NavigationStack {
      VStack {
        Button {
          authService.isPresented = true
        } label: {
          Text("Authenticate")
        }
      }
    }
  }
}

Vereinfachtes Beispiel für einen benutzerdefinierten Button

Sie können auch einfachere benutzerdefinierte Schaltflächen für jeden Anbieter erstellen:

import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import FirebaseAppleSwiftUI
import SwiftUI

// Custom Google Provider UI
class CustomGoogleProviderAuthUI: AuthProviderUI {
  private let typedProvider: GoogleProviderSwift
  var provider: AuthProviderSwift { typedProvider }
  let id: String = "google.com"
  
  init() {
    typedProvider = GoogleProviderSwift()
  }
  
  @MainActor func authButton() -> AnyView {
    AnyView(CustomGoogleButton(provider: typedProvider))
  }
}

struct CustomGoogleButton: View {
  let provider: GoogleProviderSwift
  @Environment(AuthService.self) private var authService
  
  var body: some View {
    Button {
      Task {
        try? await authService.signIn(provider)
      }
    } label: {
      HStack {
        Image(systemName: "g.circle.fill")
        Text("My Custom Google Button")
      }
      .frame(maxWidth: .infinity)
      .padding()
      .background(Color.purple) // Your custom color
      .foregroundColor(.white)
      .cornerRadius(10)
    }
  }
}

// Then use it
struct ContentView: View {
  let authService: AuthService
  
  init() {
    let configuration = AuthConfiguration()
    authService = AuthService(configuration: configuration)
      .withAppleSignIn() // Use default Apple button
    
    // Use custom Google button
    authService.registerProvider(
      providerWithButton: CustomGoogleProviderAuthUI()
    )
  }
  
  var body: some View {
    AuthPickerView {
      Text("App Content")
    }
    .environment(authService)
  }
}

Dieser Ansatz funktioniert für alle Anbieter: Google, Apple, Twitter, Facebook, Telefon und OAuth-Anbieter. Erstellen Sie einfach Ihre benutzerdefinierte Schaltflächenansicht und verpacken Sie sie in eine Klasse, die AuthProviderUI entspricht.

Methode 2: Standard-Buttons mit benutzerdefinierten Ansichten

Sie können AuthService.renderButtons() verwenden und AuthPickerView umgehen, um die Standard-Authentifizierungsschaltflächen zu rendern und gleichzeitig Ihr eigenes Layout und Ihre eigene Navigation bereitzustellen:

import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import FirebaseAppleSwiftUI
import SwiftUI

struct CustomAuthView: View {
  @Environment(AuthService.self) private var authService

  var body: some View {
    VStack(spacing: 30) {
      // Your custom logo/branding
      Image("app-logo")
        .resizable()
        .frame(width: 150, height: 150)
      
      Text("Welcome to My App")
        .font(.largeTitle)
        .fontWeight(.bold)
      
      Text("Sign in to continue")
        .font(.subheadline)
        .foregroundStyle(.secondary)
      
      // Render default auth buttons
      authService.renderButtons(spacing: 12)
        .padding()
    }
    .padding()
  }
}

struct ContentView: View {
  init() {
    let configuration = AuthConfiguration()
    
    authService = AuthService(configuration: configuration)
      .withGoogleSignIn()
      .withAppleSignIn()
  }
  
  let authService: AuthService

  var body: some View {
    NavigationStack {
      if authService.authenticationState == .authenticated {
        Text("Authenticated!")
      } else {
        CustomAuthView()
      }
    }
    .environment(authService)
  }
}

Methode 3: Benutzerdefinierte Ansichten mit benutzerdefinierter Navigation

Wenn Sie die vollständige Kontrolle über den gesamten Ablauf haben möchten, können Sie AuthPickerView umgehen und Ihr eigenes Navigationssystem erstellen:

import FirebaseAuth
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import SwiftUI

enum CustomAuthRoute {
  case signIn
  case phoneVerification
  case mfaResolution
}

struct ContentView: View {
  private let authService: AuthService
  @State private var navigationPath: [CustomAuthRoute] = []
  @State private var errorMessage: String?

  init() {
    let configuration = AuthConfiguration()
    self.authService = AuthService(configuration: configuration)
      .withGoogleSignIn()
      .withPhoneSignIn()
  }

  var body: some View {
    NavigationStack(path: $navigationPath) {
      Group {
        if authService.authenticationState == .authenticated {
          authenticatedView
        } else {
          customSignInView
        }
      }
      .navigationDestination(for: CustomAuthRoute.self) { route in
        switch route {
        case .signIn:
          customSignInView
        case .phoneVerification:
          customPhoneVerificationView
        case .mfaResolution:
          customMFAView
        }
      }
    }
    .environment(authService)
    .alert("Error", isPresented: .constant(errorMessage != nil)) {
      Button("OK") {
        errorMessage = nil
      }
    } message: {
      Text(errorMessage ?? "")
    }
  }

  var customSignInView: some View {
    VStack(spacing: 20) {
      Text("Custom Sign In")
        .font(.title)
      
      Button("Sign in with Google") {
        Task {
          do {
            let provider = GoogleProviderSwift(clientID: Auth.auth().app?.options.clientID ?? "")
            let outcome = try await authService.signIn(provider)
            
            // Handle MFA if required
            if case .mfaRequired = outcome {
              navigationPath.append(.mfaResolution)
            }
          } catch {
            errorMessage = error.localizedDescription
          }
        }
      }
      .buttonStyle(.borderedProminent)
      
      Button("Phone Sign In") {
        navigationPath.append(.phoneVerification)
      }
      .buttonStyle(.bordered)
    }
    .padding()
  }

  var customPhoneVerificationView: some View {
    Text("Custom Phone Verification View")
    // Implement your custom phone auth UI here
  }

  var customMFAView: some View {
    Text("Custom MFA Resolution View")
    // Implement your custom MFA UI here
  }

  var authenticatedView: some View {
    VStack(spacing: 20) {
      Text("Welcome!")
      Text("Email: \(authService.currentUser?.email ?? "N/A")")
      
      Button("Sign Out") {
        Task {
          try? await authService.signOut()
        }
      }
      .buttonStyle(.borderedProminent)
    }
  }
}

Wichtige Hinweise zu benutzerdefinierten Ansichten

Wenn Sie benutzerdefinierte Ansichten erstellen, müssen Sie einige Dinge selbst erledigen, die AuthPickerView automatisch übernimmt:

  1. Kontokonflikte: Implementieren Sie mit AuthServiceError.accountConflict Ihre eigene Strategie zur Konfliktlösung.
  2. MFA-Verarbeitung: Prüfen Sie SignInOutcome auf .mfaRequired und verarbeiten Sie die MFA manuell.
  3. Upgrades für anonyme Nutzer: Verknüpfung anonymer Konten verwalten, wenn shouldAutoUpgradeAnonymousUsers aktiviert ist
  4. Navigationsstatus: Navigation zwischen verschiedenen Authentifizierungsbildschirmen (Bestätigung der Telefonnummer, Passwortwiederherstellung usw.) verwalten
  5. Ladezustände: Zeigen Sie während asynchroner Authentifizierungsvorgänge Ladeanzeigen an, indem Sie authService.authenticationState beobachten.
  6. Erneute Authentifizierung: Behandeln Sie Fehler bei der erneuten Authentifizierung für vertrauliche Vorgänge (siehe Erneute Authentifizierung in benutzerdefinierten Ansichten unten).

Erneute Authentifizierung in benutzerdefinierten Ansichten

Wenn Sie benutzerdefinierte Ansichten erstellen, müssen Sie die erneute Authentifizierung verarbeiten, indem Sie bestimmte Fehler abfangen und einen eigenen Ablauf implementieren. Bei sensiblen Vorgängen werden vier Arten von Fehlern bei der erneuten Authentifizierung ausgegeben, die jeweils Kontextinformationen enthalten.

Implementierungsmuster

OAuth-Anbieter (Google, Apple, Facebook, Twitter usw.):

Fangen Sie den Fehler ab und rufen Sie reauthenticate(context:) auf, wodurch der OAuth-Vorgang automatisch verarbeitet wird:

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 operation
  }
}

E‑Mail-Adresse/Passwort:

Fehler abfangen, Passwort abfragen, Anmeldedaten erstellen und reauthenticate(with:) aufrufen:

do {
  try await authService.updatePassword(to: newPassword)
} catch let error as AuthServiceError {
  if case .emailReauthenticationRequired(let context) = error {
    // Show your password prompt UI
    let password = await promptUserForPassword()
    let credential = EmailAuthProvider.credential(
      withEmail: context.email,
      password: password
    )
    try await authService.reauthenticate(with: credential)
    try await authService.updatePassword(to: newPassword) // Retry
  }
}

Telefonnummer:

Fehler abfangen, Telefonnummer bestätigen, Anmeldedaten erstellen und reauthenticate(with:) aufrufen:

do {
  try await authService.deleteUser()
} catch let error as AuthServiceError {
  if case .phoneReauthenticationRequired(let context) = error {
    // Send verification code
    let verificationId = try await authService.verifyPhoneNumber(
      phoneNumber: context.phoneNumber
    )
    // Show your SMS code input UI
    let code = await promptUserForSMSCode()
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId,
      verificationCode: code
    )
    try await authService.reauthenticate(with: credential)
    try await authService.deleteUser() // Retry
  }
}

E‑Mail-Link:

Fehler abfangen, Bestätigungs-E‑Mail senden und eingehende URL verarbeiten:

do {
  try await authService.updatePassword(to: newPassword)
} catch let error as AuthServiceError {
  if case .emailLinkReauthenticationRequired(let context) = error {
    // Send verification email
    try await authService.sendEmailSignInLink(
      email: context.email,
      isReauth: true
    )
    // Show your "Check your email" UI
    await showCheckEmailUI()
    // When user taps the link, it opens your app with a URL
    // Handle it in your URL handler:
    // try await authService.handleSignInLink(url: url)
    // The handleSignInLink method automatically completes reauthentication
    try await authService.updatePassword(to: newPassword) // Retry
  }
}

Alle Kontextobjekte für die erneute Authentifizierung enthalten das Attribut .displayMessage für für Nutzer sichtbaren Text.

Benutzerdefinierte OAuth-Anbieter

Sie können benutzerdefinierte OAuth-Anbieter für Dienste erstellen, die über die integrierten Dienste hinausgehen:

⚠️ Wichtig:OIDC-Anbieter (OpenID Connect) müssen in den Authentifizierungseinstellungen Ihres Firebase-Projekts konfiguriert werden, bevor sie verwendet werden können. Rufen Sie in der Firebase Console Authentication → Anmeldemethode auf und fügen Sie Ihren OIDC-Anbieter mit den erforderlichen Anmeldedaten (Client-ID, Clientschlüssel, Aussteller-URL) hinzu. Außerdem müssen Sie den von Firebase bereitgestellten OAuth-Weiterleitungs-URI in der Entwicklerkonsole Ihres Anbieters registrieren. Eine ausführliche Anleitung zur Einrichtung finden Sie in der Firebase-OIDC-Dokumentation.

import FirebaseAuthSwiftUI
import FirebaseOAuthSwiftUI
import SwiftUI

struct ContentView: View {
  let authService: AuthService

  init() {
    let configuration = AuthConfiguration()
    
    authService = AuthService(configuration: configuration)
      .withOAuthSignIn(
        OAuthProviderSwift(
          providerId: "oidc.line",  // LINE OIDC provider
          scopes: ["profile", "openid", "email"],  // LINE requires these scopes
          displayName: "Sign in with LINE",
          buttonIcon: Image("line-logo"),
          buttonBackgroundColor: .green,
          buttonForegroundColor: .white
        )
      )
      .withOAuthSignIn(
        OAuthProviderSwift(
          providerId: "oidc.custom-provider",
          scopes: ["profile", "openid"],
          displayName: "Sign in with Custom",
          buttonIcon: Image(systemName: "person.circle"),
          buttonBackgroundColor: .purple,
          buttonForegroundColor: .white
        )
      )
  }

  var body: some View {
    AuthPickerView {
      Text("App Content")
    }
    .environment(authService)
  }
}