
FirebaseUI pour SwiftUI est une bibliothèque moderne, axée sur SwiftUI et basée sur Firebase Authentication, qui fournit des flux de connexion prédéfinis à votre application.
FirebaseUI pour SwiftUI présente les avantages suivants :
- UI par défaut : ajoutez un flux de connexion complet avec
AuthPickerView. - Personnalisable : affichez les boutons par défaut dans votre propre mise en page ou créez une expérience entièrement personnalisée.
- Association de comptes anonymes : vous pouvez mettre à niveau les utilisateurs anonymes au lieu de les remplacer.
- Gestion des comptes : flux intégrés pour l'inscription, la récupération de mot de passe et la gestion des comptes.
- Plusieurs fournisseurs : adresse e-mail/mot de passe, lien par e-mail, authentification par téléphone, Apple, Google, Facebook, Twitter et fournisseurs OAuth2/OIDC standards.
- Fonctionnalités d'authentification modernes : compatibilité intégrée avec l'authentification multifacteur (MFA) et les API async/await.
Avant de commencer
Ajoutez Firebase à votre projet Apple. Veillez à suivre les étapes SwiftUI.
Assurez-vous que votre application cible iOS 17 ou une version ultérieure.
Installation
FirebaseUI pour SwiftUI est fourni sous forme de package Swift. Pour installer le package dans votre projet Xcode, procédez comme suit :
Dans Xcode, cliquez sur File > Add Package Dependencies (Fichier > Ajouter des dépendances de package).
Saisissez l'URL du package :
https://github.com/firebase/FirebaseUI-iOSDans le menu Dependency Rule (Règle de dépendance), sélectionnez Up to Next Major Version (Jusqu'à la prochaine version majeure) et définissez la version minimale sur la dernière version.
Cliquez sur Add Package (Ajouter un package), puis sélectionnez les bibliothèques à ajouter à votre projet.
La bibliothèque suivante est toujours requise. Il inclut les dépendances de base, ainsi que la prise en charge de la connexion par adresse e-mail et mot de passe, et de la connexion par lien envoyé par e-mail.
FirebaseAuthSwiftUI
Si vous souhaitez accepter d'autres méthodes de connexion, sélectionnez également une ou plusieurs des bibliothèques suivantes :
FirebaseAppleSwiftUI(Se connecter avec Apple)FirebaseGoogleSwiftUI(Se connecter avec Google)FirebaseFacebookSwiftUI(Se connecter avec Facebook)FirebasePhoneAuthSwiftUI(authentification par téléphone)FirebaseTwitterSwiftUI(Se connecter avec Twitter)FirebaseOAuthSwiftUI(fournisseurs OAuth et OIDC standards tels que GitHub, Microsoft, Yahoo)
Cliquez sur Add Package (Ajouter un package) pour installer les bibliothèques sélectionnées.
Configurez le
AuthServicede FirebaseUI dans l'initialiseur de votreViewde premier niveau et transmettez le service aux vues enfants à l'aide de l'environnement.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) } }
Configurer les méthodes de connexion
Chacune des méthodes de connexion compatibles nécessite des étapes de configuration supplémentaires. Développez les sections ci-dessous et suivez les instructions pour configurer des fournisseurs individuels.
Adresse e-mail et mot de passe
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez le fournisseur Adresse e-mail/Mot de passe.
Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withEmailSignIn()
Authentification par lien envoyé par e-mail
Pour utiliser la connexion sans mot de passe avec un lien envoyé par e-mail :
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez l'option Adresse e-mail/Mot de passe, puis activez la connexion par lien d'e-mail. Notez que la connexion par adresse e-mail ou mot de passe doit être activée pour utiliser la connexion par lien envoyé par e-mail.
Ajoutez le domaine du lien à Domaines autorisés.
Configurez
ActionCodeSettings, transmettez-le àAuthConfigurationet enregistrez le fournisseur :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()Dans le même
AppDelegateque celui où vous appelezFirebaseApp.configure(), ajoutez une logique à la méthodeapplication(_:open:options:)qui renvoietruelorsque l'URL ouverte est un lien de connexion Firebase Authentication. Cette logique indique que le lien a été géré par FirebaseUI et ne doit pas être traité par d'autres gestionnaires de liens.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 } }Si vous créez des vues personnalisées, appelez
authService.handleSignInLink(url:)lorsque le lien ouvre votre application.
Apple
Pour utiliser Se connecter avec Apple :
Configurez Se connecter avec Apple :
- Activez la connexion avec Apple pour votre application sur la page Certificates, Identifiers & Profiles (Certificats, identifiants et profils) du site pour les développeurs d'Apple.
- Associez votre site Web à votre application comme décrit dans la première section de Configurer la connexion avec Apple pour le Web. Lorsque vous y êtes invité, enregistrez l'URL suivante en tant qu'URL de retour :
Vous pouvez obtenir l'ID de votre projet Firebase sur la page des paramètres de la console Firebase. Lorsque vous avez terminé, notez votre nouvel ID de service, dont vous aurez besoin dans la section suivante.https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- Créez une clé privée pour "Se connecter avec Apple". Vous aurez besoin de votre nouvelle clé privée et de votre ID de clé dans la section suivante.
- Si vous utilisez l'une des fonctionnalités de Firebase Authentication qui envoient des e-mails aux utilisateurs, y compris la connexion par lien d'e-mail, la validation de l'adresse e-mail, la révocation des modifications de compte, etc., configurez le service de relais de messagerie privé d'Apple et enregistrez
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(ou votre domaine de modèle d'e-mail personnalisé) afin qu'Apple puisse relayer les e-mails envoyés par Firebase Authentication vers des adresses e-mail Apple anonymisées.
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez Apple.
- Spécifiez l'ID de service que vous avez créé dans la section précédente.
- Dans la section OAuth code flow configuration (Configuration du flux de code OAuth), spécifiez votre ID d'équipe Apple, ainsi que la clé privée et l'ID de clé que vous avez créés dans la section précédente.
Dans Xcode, ouvrez la section Signing & Capabilities (Signature et fonctionnalités) de l'éditeur de projet, puis ajoutez la fonctionnalité Sign in with Apple (Se connecter avec Apple).
Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withAppleSignIn()
Pour utiliser Google Sign-In :
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez le fournisseur Google.
Téléchargez une nouvelle copie du fichier
GoogleService-Info.plistde votre projet et copiez-la dans votre projet Xcode. Écrasez toutes les versions existantes par la nouvelle.Ajoutez des schémas d'URL personnalisés à votre projet Xcode :
Ouvrez la configuration de votre projet : cliquez sur le nom du projet dans l'arborescence de gauche. Sélectionnez votre application dans la section TARGETS (CIBLES), puis sélectionnez l'onglet Info (Informations) et développez la section URL Types (Types d'URL).
Cliquez sur le bouton +, puis ajoutez un schéma d'URL pour votre ID client inversé. Pour trouver cette valeur, ouvrez le fichier de configuration
et recherchez la cléGoogleService-Info.plist REVERSED_CLIENT_ID. Copiez la valeur de cette clé et collez-la dans le champ Schémas d'URL de la page de configuration. Ne modifiez pas les autres champs.Une fois l'opération terminée, votre configuration doit ressembler à ce qui suit (mais avec les valeurs spécifiques à votre application) :

Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withGoogleSignIn()
Pour utiliser la connexion Facebook :
Configurez le SDK Facebook Login pour iOS en suivant les instructions sur le site Meta for Developers. Ignorez la dernière étape, "Add Facebook Login to Your Code" (Ajouter la connexion Facebook à votre code).
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez le fournisseur Facebook. Vous aurez besoin de l'ID et du code secret de l'application Facebook, disponibles sur le site Meta for Developers.
Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withFacebookSignIn()
Numéro de téléphone
Pour utiliser l'authentification par téléphone :
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez le fournisseur Téléphone.
Configurez les APN pour votre application comme indiqué dans la section Commencer à recevoir des notifications silencieuses.
Ajoutez des schémas d'URL personnalisés à votre projet Xcode :
Ouvrez la configuration de votre projet : cliquez sur le nom du projet dans l'arborescence de gauche. Sélectionnez votre application dans la section TARGETS (CIBLES), puis sélectionnez l'onglet Info (Informations) et développez la section URL Types (Types d'URL).
Cliquez sur le bouton +, puis ajoutez l'ID d'application encodé en tant que schéma d'URL. Pour trouver cette valeur, ouvrez Paramètres > Général dans la console Firebase.
Une fois l'opération terminée, votre configuration doit ressembler à ce qui suit (mais avec les valeurs spécifiques à votre application) :

Dans le même
AppDelegateque celui où vous appelezFirebaseApp.configure(), ajoutez des gestionnaires de jetons 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 } }Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withPhoneSignIn()
Twitter (X)
Pour utiliser la connexion Twitter :
Générez des identifiants d'API X en suivant les instructions sur le site X Developers.
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez le fournisseur Twitter. Vous aurez besoin de la clé API et du code secret de l'API de la console X Developer.
Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withTwitterSignIn()
Fournisseurs OAuth2 et OIDC standards
FirebaseUI est également compatible avec les fournisseurs OAuth intégrés tels que GitHub, Microsoft et Yahoo, ainsi qu'avec les fournisseurs OIDC personnalisés configurés dans Firebase Authentication.
let authService = AuthService()
.withOAuthSignIn(OAuthProviderSwift.github())
.withOAuthSignIn(OAuthProviderSwift.microsoft())
.withOAuthSignIn(OAuthProviderSwift.yahoo())
Pour les fournisseurs OIDC personnalisés, configurez d'abord le fournisseur dans Firebase Authentication, puis créez un OAuthProviderSwift avec l'ID de votre fournisseur et la configuration du bouton :
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)
Utiliser la vue d'authentification prédéfinie
FirebaseUI pour SwiftUI fournit AuthPickerView, une UI d'authentification prédéfinie et personnalisée qui gère l'intégralité du flux d'authentification pour vous. C'est le moyen le plus simple d'ajouter l'authentification à votre application.
Exemple
Voici un exemple d'utilisation de AuthPickerView, avec plusieurs fournisseurs et options de configuration :
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)
}
}
}
}
Personnalisation type
Bien que tous les paramètres AuthConfiguration soient facultatifs, la plupart des applications personnalisent au moins les paramètres suivants :
let configuration = AuthConfiguration(
logo: ImageResource.exampleLogoAsset,
customStringsBundle: .main,
tosUrl: URL(string: "https://example.com/tos"),
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
logo: image du logo affichée sur la feuille d'authentification. Pour savoir comment inclure votre propre asset d'image, consultez Ajouter des images à votre projet Xcode.customStringsBundle: utilisez des chaînes personnalisées du Bundle spécifié. Cette option est utilisée pour la localisation, mais aussi pour personnaliser les chaînes par défaut utilisées parAuthPickerView. Par exemple, pour définir le message affiché en haut de la feuille d'authentification, créezLocalizable.stringsavec le contenu suivant :"Sign in with Firebase" = "Sign in to use ExampleApp";
Éléments inclus dans la vue prédéfinie
Lorsque vous utilisez AuthPickerView, vous bénéficiez des avantages suivants :
- Présentation de la feuille : l'UI d'authentification s'affiche sous forme de feuille modale.
- Navigation intégrée : navigation automatique entre les écrans de connexion, de récupération de mot de passe, de MFA, de lien par e-mail et de validation du numéro de téléphone
- Gestion de l'état d'authentification : bascule automatiquement entre l'UI d'authentification et votre contenu en fonction de
authService.authenticationState - Contrôle via
isPresented: contrôlez l'affichage de la feuille d'authentification en définissantauthService.isPresented = true/false.
Comportements avisés
La valeur par défaut de AuthPickerView est basée sur la façon de gérer plusieurs scénarios complexes :
1. Résolution des conflits de compte
Lorsqu'un conflit de compte se produit (par exemple, lors de la connexion avec un identifiant déjà associé à un autre compte), AuthPickerView le gère automatiquement :
- Conflits de mise à niveau anonyme : si
shouldAutoUpgradeAnonymousUsersest activé et qu'un conflit se produit lors de la mise à niveau anonyme, le système déconnecte automatiquement l'utilisateur anonyme et se connecte avec les nouveaux identifiants. - Autres conflits : pour les conflits d'identifiants entre des comptes non anonymes, le système stocke l'identifiant en attente et tente de l'associer une fois la connexion établie.
Ceci est géré par le AccountConflictModifier appliqué au niveau de NavigationStack.
2. Authentification multifacteur (MFA)
Lorsque l'authentification multifacteur est activée dans votre configuration :
- Détecte automatiquement quand l'authentification multifacteur est requise lors de la connexion
- Présente les écrans de résolution MFA appropriés (SMS ou TOTP)
- Gère les flux d'enregistrement et de gestion de l'authentification multifacteur
- Prend en charge les facteurs de mot de passe à usage unique (OTP) par SMS et par jeton (TOTP)
3. Gestion des exceptions
Les vues par défaut incluent la gestion des erreurs intégrée :
- Affiche des messages d'erreur conviviaux dans des boîtes de dialogue d'alerte.
- Filtre automatiquement les erreurs gérées en interne (par exemple, les erreurs d'annulation, les conflits gérés automatiquement)
- Utilise des messages d'erreur localisés via
StringUtils - Les erreurs sont propagées via la clé d'environnement
reportError.
4. Connexion par lien envoyé par e-mail
Lorsque la connexion par lien par e-mail est configurée :
- Stocke automatiquement l'adresse e-mail dans l'espace de stockage de l'application
- Gère la navigation par lien profond à partir d'un e-mail
- Gère l'intégralité du flux de validation de l'adresse e-mail
- Permet de mettre à niveau les utilisateurs anonymes via un lien envoyé par e-mail.
5. Mise à niveau automatique des utilisateurs anonymes
Lorsque shouldAutoUpgradeAnonymousUsers est activé :
- Tente d'associer automatiquement les comptes anonymes à de nouveaux identifiants de connexion
- Préserve les données utilisateur en mettant à niveau les sessions anonymes au lieu de les remplacer
- Gère les conflits de mise à niveau de façon optimale
6. Réauthentification dans les vues par défaut
Les opérations sensibles telles que la suppression de comptes, la mise à jour de mots de passe ou la désinscription de facteurs MFA nécessitent une authentification récente. Lorsque vous utilisez les vues par défaut, la réauthentification est gérée automatiquement en fonction du fournisseur de connexion de l'utilisateur.
Lorsqu'une opération sensible nécessite une réauthentification, les vues par défaut effectuent automatiquement les actions suivantes :
Fournisseurs OAuth (Google, Apple, Facebook, Twitter, etc.) : Affichez une alerte demandant à l'utilisateur de confirmer, puis obtenez automatiquement de nouveaux identifiants et terminez l'opération.
E-mail/Mot de passe : affiche une feuille invitant l'utilisateur à saisir son mot de passe avant de continuer.
Lien par e-mail : affiche une alerte demandant d'envoyer un e-mail de validation, puis une feuille contenant des instructions pour consulter l'e-mail. L'utilisateur appuie sur le lien figurant dans l'e-mail pour terminer la réauthentification.
Téléphone : affichez une alerte expliquant que la validation est nécessaire, puis présentez une feuille pour la validation du code par SMS.
L'opération est automatiquement relancée une fois la réauthentification effectuée. Aucun code supplémentaire n'est requis lorsque vous utilisez AuthPickerView ou les vues de gestion de compte intégrées (UpdatePasswordView, SignedInView, etc.).
Avancé : Créer des vues d'authentification personnalisées
Si vous avez besoin de mieux contrôler l'interface utilisateur ou le flux de navigation, vous pouvez créer vos propres vues d'authentification personnalisées tout en exploitant le AuthService pour la logique d'authentification.
Vous pouvez combiner des éléments de FirebaseUI avec une logique personnalisée de différentes manières. Les sections suivantes contiennent des exemples de certaines des approches de personnalisation que vous pouvez utiliser.
Approche 1 : Boutons personnalisés avec registerProvider()
Pour contrôler entièrement l'apparence des boutons, vous pouvez créer votre propre implémentation AuthProviderUI personnalisée qui encapsule n'importe quel fournisseur et renvoie votre vue de bouton personnalisée.
Créer une UI de fournisseur personnalisée
Voici un exemple de création d'un bouton Twitter personnalisé :
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")
}
}
}
}
}
Exemple de bouton personnalisé simplifié
Vous pouvez également créer des boutons personnalisés plus simples pour n'importe quel fournisseur :
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)
}
}
Cette approche fonctionne pour tous les fournisseurs : Google, Apple, Twitter, Facebook, téléphone et fournisseurs OAuth. Il vous suffit de créer votre vue de bouton personnalisée et de l'encapsuler dans une classe conforme à AuthProviderUI.
Approche 2 : Boutons par défaut avec vues personnalisées
Vous pouvez utiliser AuthService.renderButtons() et contourner AuthPickerView pour afficher les boutons d'authentification par défaut tout en fournissant votre propre mise en page et navigation :
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)
}
}
Approche 3 : Vues personnalisées avec navigation personnalisée
Pour un contrôle total sur l'ensemble du flux, vous pouvez contourner AuthPickerView et créer votre propre système de navigation :
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)
}
}
}
Remarques importantes concernant les vues personnalisées
Lorsque vous créez des vues personnalisées, vous devez gérer vous-même plusieurs éléments que AuthPickerView gère automatiquement :
- Conflits de compte : implémentez votre propre stratégie de résolution des conflits à l'aide de
AuthServiceError.accountConflict. - Gestion de la MFA : vérifiez
SignInOutcomepour.mfaRequiredet gérez la résolution de la MFA manuellement. - Mises à niveau des utilisateurs anonymes : gérez l'association des comptes anonymes si
shouldAutoUpgradeAnonymousUsersest activé. - État de la navigation : gérez la navigation entre les différents écrans d'authentification (validation du numéro de téléphone, récupération du mot de passe, etc.).
- États de chargement : affichez des indicateurs de chargement pendant les opérations d'authentification asynchrones en observant
authService.authenticationState. - Nouvelle authentification : gérez les erreurs de nouvelle authentification pour les opérations sensibles (voir Nouvelle authentification dans les vues personnalisées ci-dessous).
Réauthentification dans les vues personnalisées
Lorsque vous créez des vues personnalisées, gérez la réauthentification en interceptant des erreurs spécifiques et en implémentant votre propre flux. Les opérations sensibles génèrent quatre types d'erreurs de réauthentification, chacune contenant des informations contextuelles.
Modèles d'implémentation
Fournisseurs OAuth (Google, Apple, Facebook, Twitter, etc.) :
Interceptez l'erreur et appelez reauthenticate(context:), qui gère automatiquement le flux 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
}
}
Adresse e-mail/Mot de passe :
Interceptez l'erreur, demandez le mot de passe, créez des identifiants et appelez 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
}
}
Téléphone :
Interceptez l'erreur, validez le numéro de téléphone, créez un identifiant et appelez 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
}
}
Lien de l'e-mail :
Interceptez l'erreur, envoyez l'e-mail de validation et gérez l'URL entrante :
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
}
}
Tous les objets de contexte de réauthentification incluent une propriété .displayMessage pour le texte visible par l'utilisateur.
Fournisseurs OAuth personnalisés
Vous pouvez créer des fournisseurs OAuth personnalisés pour des services autres que ceux intégrés :
⚠️ Important : Les fournisseurs OIDC (OpenID Connect) doivent être configurés dans les paramètres d'authentification de votre projet Firebase avant de pouvoir être utilisés. Dans la console Firebase, accédez à Authentication → Sign-in method (Authentification → Mode de connexion), puis ajoutez votre fournisseur OIDC avec les identifiants requis (ID client, code secret du client, URL de l'émetteur). Vous devez également enregistrer l'URI de redirection OAuth fourni par Firebase dans la console de développement de votre fournisseur. Pour obtenir des instructions de configuration détaillées, consultez la documentation Firebase sur 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)
}
}