Anmeldung mit FirebaseUI in Ihre iOS-App einfügen

FirebaseUI für SwiftUI ist eine moderne, auf SwiftUI basierende Bibliothek, die auf Firebase Authentication aufbaut und vorgefertigte Anmeldeabläufe für Ihre App bietet.

FirebaseUI für SwiftUI bietet folgende Vorteile:

  • Meinungsstarke 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 Umgebung erstellen.
  • Verknüpfung anonymer Konten: Sie können anonyme Nutzer optional upgraden, anstatt sie zu ersetzen.
  • Kontoverwaltung: Integrierte Abläufe für die Registrierung, die Passwortwiederherstellung und die 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 die Multi-Faktor-Authentifizierung (MFA) und asynchrone/await-APIs.

Hinweis

Installation

FirebaseUI für 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 (Datei > Paketabhängigkeiten hinzufügen).

  2. Geben Sie die Paket-URL ein:

    https://github.com/firebase/FirebaseUI-iOS
    
  3. Wählen Sie im Menü Dependency Rule (Abhängigkeitsregel) die Option Up to Next Major Version (Bis zur nächsten Hauptversion) aus und legen Sie die Mindestversion auf die aktuelle Version fest.

  4. Klicken Sie auf 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 mit 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 Paket hinzufügen, um die ausgewählten Bibliotheken zu installieren.

  6. Konfigurieren Sie AuthService von FirebaseUI im Initialisierer Ihrer View auf oberster Ebene 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 einige 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 in der Firebase-Konsole unter Sicherheit > Authentifizierung > Anmeldemethode 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-Adresse/Passwort und dann die Anmeldung per E-Mail-Link. Hinweis: Die Anmeldung per E-Mail-Adresse oder Passwort muss aktiviert sein, damit die Anmeldung per E-Mail-Link verwendet werden kann.

  2. Fügen Sie die Linkdomain 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 die App über den Link geöffnet wird.

Apple

So verwenden Sie „Über Apple anmelden“:

  1. „Über Apple anmelden“ konfigurieren:

    1. Aktivieren Sie die Anmeldung mit Apple für Ihre App auf der Seite Certificates, Identifiers & Profiles (Zertifikate, Kennungen und Profile) auf der Apple-Entwicklerwebsite.
    2. Verknüpfen Sie Ihre Website mit Ihrer App, wie im ersten Abschnitt von Mit Apple im Web anmelden beschrieben. Registrieren Sie die folgende URL als Return-URL, wenn Sie dazu aufgefordert werden:
      https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
      Sie finden die Firebase-Projekt-ID auf der Seite FirebaseKonsoleneinstellungen. Notieren Sie sich nach Abschluss 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, mit denen E‑Mails an Nutzer gesendet werden, z. B. die Anmeldung per E‑Mail-Link, die Bestätigung der E‑Mail-Adresse oder den Widerruf von Kontoänderungen, müssen Sie den privaten E‑Mail-Relay-Dienst von Apple konfigurieren und noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (oder Ihre benutzerdefinierte E‑Mail-Vorlagendomain) registrieren, damit Apple E‑Mails, die von Firebase Authentication an anonymisierte Apple-E‑Mail-Adressen gesendet werden, weiterleiten kann.
  2. Aktivieren Sie Apple im Bereich Sicherheit > Authentifizierung > Anmeldemethode der Firebase-Konsole.

    • 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 Signieren & Funktionen des Projekteditors und fügen Sie die Funktion 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. Überschreiben Sie alle vorhandenen Versionen mit der neuen.

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

    1. Öffnen Sie die Projektkonfiguration: Klicken Sie in der linken Baumansicht auf den Projektnamen. Wählen Sie im Bereich ZIELE Ihre App aus, dann den Tab Info und maximieren Sie den Bereich URL-Typen.

    2. Klicken Sie auf die Schaltfläche + 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 den Facebook-Login:

  1. Richten Sie das Facebook-Anmelde-SDK für iOS gemäß der Anleitung auf der Meta for Developers-Website ein. Überspringen Sie den letzten Schritt „Facebook-Login zu Ihrem Code hinzufügen“.

  2. Aktivieren Sie in der Firebase-Konsole im Bereich Sicherheit > Authentifizierung > Anmeldemethode 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 in der Firebase-Konsole im Bereich Sicherheit > Authentifizierung > Anmeldemethode den Anbieter Telefon.

  2. Konfigurieren Sie APNs für Ihre App gemäß der Anleitung im Abschnitt Stille Benachrichtigungen empfangen.

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

    1. Öffnen Sie die Projektkonfiguration: Klicken Sie in der linken Baumansicht auf den Projektnamen. Wählen Sie im Bereich ZIELE Ihre App aus, dann den Tab Info und maximieren Sie den Bereich URL-Typen.

    2. Klicken Sie auf die Schaltfläche + und fügen Sie Ihre 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 im selben AppDelegate, in dem 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 Developers-Website folgen.

  2. Aktivieren Sie in der Firebase-Konsole unter Sicherheit > Authentifizierung > Anmeldemethode 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())

Bei benutzerdefinierten OIDC-Anbietern müssen Sie den Anbieter zuerst in Firebase Authentication konfigurieren und dann ein OAuthProviderSwift mit Ihrer Anbieter-ID und der Schaltflächenkonfiguration erstellen:

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 vorgefertigte, meinungsstarke Authentifizierungs-UI, die den gesamten Authentifizierungsablauf für Sie übernimmt. Dies ist die einfachste Methode, um Ihrer App die 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 zwar 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 Logo, das auf dem Authentifizierungsblatt angezeigt wird. Informationen zum Einbinden eines eigenen Bild-Assets finden Sie unter Bilder zum 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 Meldung 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:

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

Fundierte Verhaltensweisen

Die Standard-AuthPickerView ist darauf ausgelegt, wie mit mehreren komplexen Szenarien umgegangen werden soll:

1. Kontokonflikte beheben

Wenn ein Konto in Konflikt gerät (z.B. wenn Sie sich mit Anmeldedaten anmelden, die bereits mit einem anderen Konto verknüpft sind), wird dies automatisch von AuthPickerView behandelt:

  • Anonyme Upgrade-Konflikte: Wenn shouldAutoUpgradeAnonymousUsers aktiviert ist und bei einem anonymen Upgrade ein Konflikt auftritt, meldet das System den anonymen Nutzer automatisch ab und meldet ihn mit den neuen Anmeldedaten an.
  • Andere Konflikte: Bei Anmeldedatenkonflikten zwischen nicht anonymen Konten speichert das System die ausstehenden Anmeldedaten und versucht, sie nach erfolgreicher Anmeldung zu verknüpfen.

Dies wird durch den AccountConflictModifier auf NavigationStack-Ebene gehandhabt.

2. Multi-Faktor-Authentifizierung (MFA)

Wenn MFA in Ihrer Konfiguration aktiviert ist:

  • Erkennt automatisch, wann bei der Anmeldung eine 2‑Faktor-Authentifizierung erforderlich ist
  • Es werden geeignete Bildschirme für die MFA-Auflösung (SMS oder TOTP) angezeigt.
  • Verarbeitet Abläufe für die Registrierung und Verwaltung von MFA
  • Unterstützt sowohl SMS-basierte als auch TOTP-Faktoren (Time-based One-Time Password)
3. Fehlerbehandlung

Die Standardansichten enthalten eine integrierte Fehlerbehandlung:

  • Nutzerfreundliche Fehlermeldungen in Benachrichtigungsdialogfeldern anzeigen
  • Fehler, die intern behandelt werden (z. B. Kündigungsfehler, automatisch behandelte Konflikte), werden automatisch herausgefiltert.
  • Verwendet lokalisierte Fehlermeldungen über StringUtils
  • Fehler werden über den Umgebungsschlüssel reportError weitergegeben.

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

  • Speichert die E-Mail-Adresse automatisch im App-Speicher
  • Verarbeitet die Deeplink-Navigation aus E-Mails
  • Verwaltet den gesamten Ablauf der E-Mail-Bestätigung
  • Unterstützt Upgrades anonymer Nutzer über E‑Mail-Link
5. Automatische Umstellung für anonyme Nutzer

Wenn shouldAutoUpgradeAnonymousUsers aktiviert ist, gilt Folgendes:

  • Es wird automatisch versucht, anonyme Konten mit neuen Anmeldedaten zu verknüpfen.
  • Nutzerdaten bleiben erhalten, da anonyme Sitzungen aktualisiert und nicht ersetzt werden.
  • Der Agent geht angemessen mit Upgradekonflikten um.
6. Erneute Authentifizierung in Standardansichten

Für sensible Vorgänge wie das Löschen von Konten, das Aktualisieren von Passwörtern oder das Entfernen von MFA-Faktoren ist eine aktuelle Authentifizierung erforderlich. Bei Verwendung von Standardansichten wird die erneute Authentifizierung automatisch auf Grundlage des Anmeldeanbieters des Nutzers durchgeführt.

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

  • OAuth-Anbieter (Google, Apple, Facebook, Twitter usw.): Zeigen Sie eine Benachrichtigung an, in der der Nutzer aufgefordert wird, die Aktion zu bestätigen. Rufen Sie dann automatisch neue Anmeldedaten ab und führen Sie die Aktion aus.

  • E-Mail/Passwort: Zeigen Sie ein Sheet an, 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 aufgefordert wird, eine Bestätigungs-E‑Mail zu senden. Anschließend wird ein Sheet mit einer Anleitung zum Prüfen der E‑Mail angezeigt. Der Nutzer tippt auf den Link in der E‑Mail, um die Reauthentifizierung abzuschließen.

  • Telefon: Zeigen Sie eine Benachrichtigung an, in der erklärt wird, dass eine Bestätigung erforderlich ist, und präsentieren Sie dann ein Sheet für die SMS-Code-Bestätigung.

Der Vorgang wird nach erfolgreicher erneuter Authentifizierung automatisch wiederholt. Bei Verwendung von AuthPickerView oder den integrierten Ansichten für die Kontoverwaltung (UpdatePasswordView, SignedInView usw.) ist kein zusätzlicher Code erforderlich.

Erweitert: Benutzerdefinierte Ansichten für die Authentifizierung erstellen

Wenn Sie mehr Kontrolle über die Benutzeroberfläche oder den Navigationsfluss benötigen, können Sie eigene benutzerdefinierte Authentifizierungsansichten erstellen und dabei weiterhin die AuthService für die Authentifizierungslogik nutzen.

Sie können Elemente von FirebaseUI auf viele Arten mit benutzerdefinierter Logik kombinieren. In den folgenden Abschnitten finden Sie Beispiele für einige der Anpassungsansätze, die Sie verwenden können.

Ansatz 1: Benutzerdefinierte Schaltflächen mit registerProvider()

Wenn Sie die Darstellung von Buttons vollständig selbst bestimmen möchten, können Sie eine eigene AuthProviderUI-Implementierung erstellen, die einen beliebigen Anbieter umschließt und Ihre benutzerdefinierte Button-Ansicht zurückgibt.

Benutzerdefinierte Anbieter-UI erstellen

So erstellen Sie beispielsweise eine benutzerdefinierte 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)
  }
}

Dieses Verfahren funktioniert für alle Anbieter: Google, Apple, Twitter, Facebook, Telefon und OAuth-Anbieter. Erstellen Sie einfach Ihre benutzerdefinierte Schaltflächenansicht und umschließen Sie sie mit einer Klasse, die AuthProviderUI entspricht.

Ansatz 2: Standardschaltflächen mit benutzerdefinierten Ansichten

Sie können AuthService.renderButtons() verwenden und AuthPickerView umgehen, um die Standardauthentifizierungs-Schaltflä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 ein 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 mehrere Dinge selbst erledigen, die von AuthPickerView automatisch ausgeführt werden:

  1. Kontokonflikte: Implementieren Sie Ihre eigene Strategie zur Konfliktlösung mit AuthServiceError.accountConflict.
  2. MFA-Verarbeitung: Prüfen Sie SignInOutcome auf .mfaRequired und beheben Sie die MFA manuell.
  3. Upgrades für anonyme Nutzer: Verknüpfung anonymer Konten verarbeiten, wenn shouldAutoUpgradeAnonymousUsers aktiviert ist
  4. Navigationsstatus: Navigation zwischen verschiedenen Authentifizierungsbildschirmen verwalten (Telefonbestätigung, Passwortwiederherstellung usw.)
  5. Ladestatus: 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 durch Abfangen bestimmter Fehler und Implementieren eines eigenen Ablaufs verarbeiten. Bei sensiblen Vorgängen werden vier Arten von Reauthentifizierungsfehlern ausgegeben, die jeweils Kontextinformationen enthalten.

Implementierungsmuster

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

Fangen Sie den Fehler ab und rufen Sie reauthenticate(context:) auf, um den OAuth-Ablauf automatisch zu verarbeiten:

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:

Fangen Sie den Fehler ab, fordern Sie das Passwort an, erstellen Sie die Anmeldedaten und rufen Sie reauthenticate(with:) auf:

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

Telefon:

Fangen Sie den Fehler ab, bestätigen Sie die Telefonnummer, erstellen Sie Anmeldedaten und rufen Sie reauthenticate(with:) auf:

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:

Fangen Sie den Fehler ab, senden Sie eine Bestätigungs-E‑Mail und verarbeiten Sie die eingehende URL:

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 Reauthentifizierungskontextobjekte enthalten eine .displayMessage-Eigenschaft für nutzerorientierten Text.

Benutzerdefinierte OAuth-Anbieter

Sie können benutzerdefinierte OAuth-Anbieter für Dienste erstellen, die nicht zu den integrierten gehören:

⚠️ 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 Authentifizierung → 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-Dokumentation zu OIDC.

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