
FirebaseUI per SwiftUI è una libreria moderna, basata su SwiftUI e creata su Firebase Authentication che fornisce flussi di accesso predefiniti alla tua app.
FirebaseUI per SwiftUI offre i seguenti vantaggi:
- UI predefinita basata su opinioni: aggiungi un flusso di accesso completo con
AuthPickerView. - Personalizzabile: esegui il rendering dei pulsanti predefiniti nel tuo layout o crea un'esperienza completamente personalizzata.
- Collegamento anonimo degli account: esegui l'upgrade facoltativo degli utenti anonimi anziché sostituirli.
- Gestione dell'account: flussi integrati per la registrazione, il recupero della password e la gestione dell'account.
- Più provider: email/password, link via email, autenticazione telefonica, Apple, Google, Facebook, Twitter e provider OAuth2/OIDC standard.
- Funzionalità di autenticazione moderna: supporto integrato per l'autenticazione a più fattori (MFA) e API async/await.
Prima di iniziare
Aggiungi Firebase al tuo progetto Apple. Assicurati di completare i passaggi di SwiftUI.
Assicurati che la tua app abbia come target iOS 17 o versioni successive.
Installazione
FirebaseUI per SwiftUI viene fornito come pacchetto Swift. Per installare il pacchetto nel tuo progetto Xcode:
In Xcode, fai clic su File > Add Package Dependencies (File > Aggiungi dipendenze pacchetto).
Inserisci l'URL del pacchetto:
https://github.com/firebase/FirebaseUI-iOSNel menu Regola di dipendenza, seleziona Fino alla prossima versione principale e imposta la versione minima su l'ultima release.
Fai clic su Aggiungi pacchetto, quindi seleziona le librerie da aggiungere al progetto.
La seguente libreria è sempre obbligatoria. Include le dipendenze principali e il supporto per l'accesso con email e password e l'accesso con link via email.
FirebaseAuthSwiftUI
Se vuoi supportare altri metodi di accesso, seleziona anche una o più delle seguenti librerie:
FirebaseAppleSwiftUI(Accedi con Apple)FirebaseGoogleSwiftUI(Accedi con Google)FirebaseFacebookSwiftUI(Accedi con Facebook)FirebasePhoneAuthSwiftUI(autenticazione telefonica)FirebaseTwitterSwiftUI(Accedi con Twitter)FirebaseOAuthSwiftUI(provider OAuth e OIDC standard come GitHub, Microsoft, Yahoo)
Fai clic su Aggiungi pacchetto per installare le librerie selezionate.
Configura
AuthServicedi FirebaseUI nell'inizializzatore diViewdi primo livello e passa il servizio alle visualizzazioni secondarie utilizzando l'ambiente.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) } }
Configurare i metodi di accesso
Ciascuno dei metodi di accesso supportati richiede alcuni passaggi di configurazione aggiuntivi. Espandi le sezioni di seguito e segui le istruzioni per configurare i singoli fornitori.
Indirizzo email e password
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva il provider Email/Password.
Registra il provider nell'istanza
AuthService:let authService = AuthService() .withEmailSignIn()
Autenticazione tramite link email
Per utilizzare l'accesso tramite link via email senza password:
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva Email/Password, quindi attiva l'accesso tramite link via email. Tieni presente che l'accesso con email o password deve essere abilitato per utilizzare l'accesso tramite link via email.
Aggiungi il dominio del link a Domini autorizzati.
Configura
ActionCodeSettings, passalo aAuthConfiguratione registra il fornitore: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()Nello stesso
AppDelegatein cui chiamiFirebaseApp.configure(), aggiungi la logica al metodoapplication(_:open:options:)che restituiscetruequando l'URL aperto è un link di accesso Firebase Authentication. Questa logica indica che il link è stato gestito da FirebaseUI e non deve essere elaborato da altri gestori di link.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 } }Se crei visualizzazioni personalizzate, chiama
authService.handleSignInLink(url:)quando il link apre l'app.
Apple
Per utilizzare Accedi con Apple:
Configura Accedi con Apple:
- Attiva l'accesso con Apple per la tua app nella pagina Certificati, identificatori e profili del sito per sviluppatori di Apple.
- Associa il tuo sito web alla tua app come descritto nella prima sezione
di Configurare Accedi con Apple per il web. Quando richiesto, registra il seguente URL come URL di ritorno:
Puoi ottenere l'ID progetto Firebase nella pagina delle impostazioni della console Firebase. Al termine, annota il nuovo ID servizio, che ti servirà nella sezione successiva.https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- Crea una chiave privata per Accedi con Apple. Nella sezione successiva avrai bisogno della nuova chiave privata e dell'ID chiave.
- Se utilizzi una delle funzionalità di Firebase Authentication che inviano email agli utenti,
tra cui l'accesso tramite link email, la verifica dell'indirizzo email, la revoca
della modifica dell'account e altre, configura il servizio di inoltro email privato di Apple
e registra
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(o il dominio del modello di email personalizzato) in modo che Apple possa inoltrare le email inviate da Firebase Authentication a indirizzi email Apple anonimizzati.
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva Apple.
- Specifica l'ID servizio che hai creato nella sezione precedente.
- Nella sezione Configurazione del flusso di codice OAuth, specifica l'ID team Apple e la chiave privata e l'ID chiave che hai creato nella sezione precedente.
In Xcode, apri la sezione Signing & Capabilities (Firma e funzionalità) dell'editor di progetto e aggiungi la funzionalità Accedi con Apple.
Registra il provider nell'istanza
AuthService:let authService = AuthService() .withAppleSignIn()
Per utilizzare Accesso Google:
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva il provider Google.
Scarica una nuova copia del file
GoogleService-Info.plistdel progetto e copiala nel progetto Xcode. Sovrascrivi le versioni esistenti con quella nuova.Aggiungi schemi URL personalizzati al progetto Xcode:
Apri la configurazione del progetto: fai clic sul nome del progetto nella visualizzazione ad albero a sinistra. Seleziona la tua app dalla sezione TARGET, quindi seleziona la scheda Informazioni ed espandi la sezione Tipi di URL.
Fai clic sul pulsante + e aggiungi uno schema URL per l'ID client invertito. Per trovare questo valore, apri il file di configurazione
e cerca la chiaveGoogleService-Info.plist REVERSED_CLIENT_ID. Copia il valore di questa chiave e incollalo nella casella Schemi URL nella pagina di configurazione. Lascia invariati gli altri campi.Al termine, la configurazione dovrebbe essere simile alla seguente (ma con i valori specifici dell'applicazione):

Registra il provider nell'istanza
AuthService:let authService = AuthService() .withGoogleSignIn()
Per utilizzare l'accesso con Facebook:
Configura l'SDK Facebook Login per iOS seguendo le istruzioni sul sito Meta for Developers. Salta il passaggio finale "Aggiungi l'accesso con Facebook al tuo codice".
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva il provider Facebook. Avrai bisogno dell'ID app Facebook e del client secret dal sito Meta for Developers.
Registra il provider nell'istanza
AuthService:let authService = AuthService() .withFacebookSignIn()
Numero di telefono
Per utilizzare l'autenticazione telefonica:
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva il provider Telefono.
Configura APN per la tua app come indicato nella sezione Inizia a ricevere notifiche silenziose.
Aggiungi schemi URL personalizzati al progetto Xcode:
Apri la configurazione del progetto: fai clic sul nome del progetto nella visualizzazione ad albero a sinistra. Seleziona la tua app dalla sezione TARGET, quindi seleziona la scheda Informazioni ed espandi la sezione Tipi di URL.
Fai clic sul pulsante + e aggiungi l'ID app codificato come schema URL. Per trovare questo valore, apri Impostazioni > Generali nella console Firebase.
Al termine, la configurazione dovrebbe essere simile alla seguente (ma con i valori specifici dell'applicazione):

Nello stesso
AppDelegatein cui chiamiFirebaseApp.configure(), aggiungi i gestori di token APNs: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 } }Registra il provider nell'istanza
AuthService:let authService = AuthService() .withPhoneSignIn()
Twitter (X)
Per utilizzare l'accesso a Twitter:
Genera le credenziali API X seguendo le istruzioni sul sito X Developers.
Nella sezione Sicurezza > Autenticazione > Metodo di accesso della console Firebase, attiva il provider Twitter. Avrai bisogno della chiave API e dell'API secret della console per sviluppatori X.
Registra il provider nell'istanza
AuthService:let authService = AuthService() .withTwitterSignIn()
Provider OAuth2 e OIDC standard
FirebaseUI supporta anche i provider OAuth integrati come GitHub, Microsoft e Yahoo, nonché i provider OIDC personalizzati configurati in Firebase Authentication.
let authService = AuthService()
.withOAuthSignIn(OAuthProviderSwift.github())
.withOAuthSignIn(OAuthProviderSwift.microsoft())
.withOAuthSignIn(OAuthProviderSwift.yahoo())
Per i provider OIDC personalizzati, configura prima il provider in Firebase
Authentication, poi crea un OAuthProviderSwift con l'ID provider e
la configurazione del pulsante:
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)
Utilizzo della visualizzazione di autenticazione predefinita
FirebaseUI per SwiftUI fornisce AuthPickerView, un'interfaccia utente di autenticazione predefinita che gestisce l'intero flusso di autenticazione per te. Questo è
il modo più semplice per aggiungere l'autenticazione alla tua app.
Esempio
Ecco un esempio di AuthPickerView in uso, con più provider e
opzioni di configurazione:
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)
}
}
}
}
Personalizzazione tipica
Sebbene tutti i parametri AuthConfiguration siano facoltativi, la maggior parte delle app
personalizza almeno le seguenti impostazioni:
let configuration = AuthConfiguration(
logo: ImageResource.exampleLogoAsset,
customStringsBundle: .main,
tosUrl: URL(string: "https://example.com/tos"),
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
logo: l'immagine del logo visualizzata nel foglio di autenticazione. Per informazioni sull'inclusione di una risorsa immagine personalizzata, consulta Aggiungere immagini al progetto Xcode.customStringsBundle: utilizza le stringhe personalizzate del bundle specificato. Questo valore viene utilizzato per la localizzazione, ma anche per personalizzare le stringhe predefinite utilizzate daAuthPickerView. Ad esempio, per impostare il messaggio visualizzato nella parte superiore del foglio di autenticazione, creaLocalizable.stringscon i seguenti contenuti:"Sign in with Firebase" = "Sign in to use ExampleApp";
Cosa è incluso nella visualizzazione predefinita
Quando utilizzi AuthPickerView, ottieni:
- Presentazione del foglio: l'interfaccia utente di autenticazione viene visualizzata come un foglio modale
- Navigazione integrata: navigazione automatica tra le schermate di accesso, recupero password, MFA, link via email e verifica telefonica
- Gestione dello stato di autenticazione: passa automaticamente dall'interfaccia utente di autenticazione ai tuoi contenuti in base a
authService.authenticationState - Controllo tramite
isPresented: controlla quando viene visualizzato il foglio di autorizzazione impostandoauthService.isPresented = true/false
Comportamenti "guidati"
Il AuthPickerView predefinito è orientato alla gestione di diversi scenari complessi:
1. Risoluzione dei conflitti tra account
Quando si verifica un conflitto di account (ad es. l'accesso con una credenziale già collegata a un altro account), AuthPickerView lo gestisce automaticamente:
- Conflitti di upgrade anonimi: se
shouldAutoUpgradeAnonymousUsersè abilitato e si verifica un conflitto durante l'upgrade anonimo, il sistema esegue automaticamente il logout dell'utente anonimo e l'accesso con la nuova credenziale. - Altri conflitti: per i conflitti delle credenziali tra account non anonimi, il sistema memorizza le credenziali in attesa e tenta di collegarle dopo l'accesso riuscito.
Questa operazione viene gestita da AccountConflictModifier applicato a livello di NavigationStack.
2. Autenticazione a più fattori (MFA)
Quando l'autenticazione a più fattori (MFA) è attivata nella configurazione:
- Rileva automaticamente quando è richiesta l'autenticazione a più fattori durante l'accesso
- Mostra le schermate di risoluzione MFA appropriate (SMS o TOTP)
- Gestisce i flussi di registrazione e gestione dell'autenticazione a più fattori
- Supporta fattori basati su SMS e password unica (TOTP) basata sul tempo
3. Gestione degli errori
Le visualizzazioni predefinite includono la gestione degli errori integrata:
- Mostra messaggi di errore di facile comprensione nelle finestre di dialogo di avviso
- Filtra automaticamente gli errori gestiti internamente (ad es. errori di annullamento, conflitti gestiti automaticamente)
- Utilizza messaggi di errore localizzati tramite
StringUtils - Gli errori vengono propagati tramite la chiave dell'ambiente
reportError
4. Accesso tramite link via email
Quando l'accesso tramite link via email è configurato:
- Memorizza automaticamente l'indirizzo email nello spazio di archiviazione dell'app
- Gestisce la navigazione tramite link diretto dall'email
- Gestisce l'intero flusso di verifica dell'email
- Supporta gli upgrade degli utenti anonimi tramite link email
5. Upgrade automatico dell'utente anonimo
Quando shouldAutoUpgradeAnonymousUsers è attivato:
- Tenta automaticamente di collegare gli account anonimi con le nuove credenziali di accesso
- Conserva i dati utente eseguendo l'upgrade anziché sostituire le sessioni anonime
- Gestisce facilmente i conflitti di upgrade
6. Riautenticazione nelle visualizzazioni predefinite
Le operazioni sensibili, come l'eliminazione di account, l'aggiornamento delle password o l'annullamento della registrazione dei fattori MFA, richiedono un'autenticazione recente. Quando utilizzi le visualizzazioni predefinite, la riautenticazione viene gestita automaticamente in base al fornitore di accesso dell'utente.
Quando un'operazione sensibile richiede la riautenticazione, le visualizzazioni predefinite vengono automaticamente:
Fornitori OAuth (Google, Apple, Facebook, Twitter e così via): Mostra un avviso che chiede all'utente di confermare, quindi ottieni automaticamente nuove credenziali e completa l'operazione.
Email/Password: mostra un foglio che chiede all'utente di inserire la password prima di continuare.
Link email: mostra un avviso che chiede di inviare un'email di verifica, quindi presenta un foglio con le istruzioni per controllare l'email. L'utente tocca il link nell'email per completare la riautenticazione.
Telefono: mostra un avviso che spiega che è necessaria la verifica, quindi presenta un foglio per la verifica del codice SMS.
L'operazione viene ritentata automaticamente dopo la riautenticazione. Non è necessario alcun codice aggiuntivo quando utilizzi AuthPickerView o le visualizzazioni di gestione degli account integrate (UpdatePasswordView, SignedInView e così via).
Avanzato: creazione di visualizzazioni di autenticazione personalizzate
Se hai bisogno di un maggiore controllo sull'interfaccia utente o sul flusso di navigazione, puoi creare visualizzazioni di autenticazione personalizzate sfruttando comunque AuthService per la logica di autenticazione.
Puoi combinare elementi di FirebaseUI con logica personalizzata in molti modi. Le seguenti sezioni contengono esempi di alcuni degli approcci di personalizzazione che potresti utilizzare.
Approccio 1: pulsanti personalizzati con registerProvider()
Per un controllo completo sull'aspetto del pulsante, puoi creare una tua implementazione AuthProviderUI personalizzata che esegua il wrapping di qualsiasi fornitore e restituisca la visualizzazione del pulsante personalizzato.
Creazione di un'interfaccia utente del fornitore personalizzata
Ecco come creare un pulsante Twitter personalizzato come esempio:
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")
}
}
}
}
}
Esempio di pulsante personalizzato semplificato
Puoi anche creare pulsanti personalizzati più semplici per qualsiasi fornitore:
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)
}
}
Questo approccio funziona per tutti i provider: Google, Apple, Twitter, Facebook, telefono e provider OAuth. Ti basta creare la visualizzazione del pulsante personalizzato e racchiuderla in una classe conforme a AuthProviderUI.
Approccio 2: pulsanti predefiniti con visualizzazioni personalizzate
Puoi utilizzare AuthService.renderButtons() e ignorare AuthPickerView per eseguire il rendering dei pulsanti di autenticazione predefiniti fornendo il tuo layout e la tua navigazione:
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)
}
}
Approccio 3: visualizzazioni personalizzate con navigazione personalizzata
Per un controllo completo dell'intero flusso, puoi ignorare AuthPickerView e creare il tuo sistema di navigazione:
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)
}
}
}
Considerazioni importanti per le viste personalizzate
Quando crei visualizzazioni personalizzate, devi gestire autonomamente diverse operazioni che AuthPickerView gestisce automaticamente:
- Conflitti tra account: implementa la tua strategia di risoluzione dei conflitti utilizzando
AuthServiceError.accountConflict - Gestione MFA: controlla
SignInOutcomeper.mfaRequirede gestisci manualmente la risoluzione MFA - Upgrade degli utenti anonimi: gestisci il collegamento degli account anonimi se
shouldAutoUpgradeAnonymousUsersè abilitato - Stato di navigazione: gestisci la navigazione tra le diverse schermate di autenticazione (verifica del telefono, recupero della password e così via).
- Stati di caricamento: mostra gli indicatori di caricamento durante le operazioni di autenticazione asincrona osservando
authService.authenticationState - Riautenticazione: gestisci gli errori di riautenticazione per le operazioni sensibili (vedi Riautenticazione nelle visualizzazioni personalizzate di seguito)
Riautenticazione nelle visualizzazioni personalizzate
Quando crei visualizzazioni personalizzate, gestisci la riautenticazione rilevando errori specifici e implementando il tuo flusso. Le operazioni sensibili generano quattro tipi di errori di riautenticazione, ognuno dei quali contiene informazioni di contesto.
Pattern di implementazione
Fornitori OAuth (Google, Apple, Facebook, Twitter e così via):
Rileva l'errore e chiama reauthenticate(context:), che gestisce automaticamente il flusso OAuth:
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
}
}
Email/Password:
Rileva l'errore, richiedi la password, crea le credenziali e chiama reauthenticate(with:):
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
}
}
Telefono:
Rileva l'errore, verifica il telefono, crea le credenziali e chiama reauthenticate(with:):
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
}
}
Link email:
Rileva l'errore, invia l'email di verifica e gestisci l'URL in entrata:
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
}
}
Tutti gli oggetti di contesto di riautenticazione includono una proprietà .displayMessage per il testo rivolto agli utenti.
Provider OAuth personalizzati
Puoi creare provider OAuth personalizzati per servizi diversi da quelli integrati:
⚠️ Importante:i provider OIDC (OpenID Connect) devono essere configurati nelle impostazioni di autenticazione del progetto Firebase prima di poter essere utilizzati. Nella console Firebase, vai a Autenticazione → Metodo di accesso e aggiungi il tuo provider OIDC con le credenziali richieste (ID client, segreto client, URL emittente). Devi anche registrare l'URI di reindirizzamento OAuth fornito da Firebase nella console per sviluppatori del tuo provider. Per istruzioni di configurazione dettagliate, consulta la documentazione di Firebase 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)
}
}