
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 avec des opinions : 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 : mettez à niveau les utilisateurs anonymes au lieu de les remplacer (facultatif).
- Gestion de compte : flux intégrés pour l'inscription, la récupération de mot de passe et la gestion de compte.
- Plusieurs fournisseurs : 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 moderne : 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 en tant que 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 Règle de dépendance, sélectionnez Jusqu'à la prochaine version majeure et définissez la version minimale sur la dernière version.
Cliquez sur Ajouter un package, puis sélectionnez les bibliothèques à ajouter à votre projet.
La bibliothèque suivante est toujours requise. Il inclut les dépendances principales, 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 prendre en charge 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 et Yahoo)
Cliquez sur Ajouter un package pour installer les bibliothèques sélectionnées.
Configurez
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 des 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 les 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 par lien envoyé par e-mail :
Dans la section Sécurité > Authentification > Méthode de connexion de la console Firebase, activez Adresse e-mail/Mot de passe, puis activez la connexion par lien envoyé par e-mail. Notez que la connexion par e-mail ou mot de passe doit être activée pour utiliser la connexion par lien d'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
AppDelegatedans lequel 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 comme URL de renvoi :
Vous trouverez 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. Vous en 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 son ID dans la section suivante.
- Si vous utilisez des fonctionnalités de Firebase Authentication qui envoient des e-mails aux utilisateurs, y compris la connexion par lien e-mail, la validation d'adresse e-mail, la révocation de modification de compte, etc., configurez le service de relais de messagerie privé d'Apple et enregistrez
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(ou le domaine de votre 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 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 Signature et capacités de l'éditeur de projet et ajoutez la capacité 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. Remplacez 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 CIBLES, puis l'onglet Infos et développez la section 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 la zone URL Schemes (Schémas d'URL) sur la page de configuration. Ne modifiez pas les autres champs.Une fois terminée, votre configuration devrait ressembler à ce qui suit (mais avec vos valeurs spécifiques à l'application) :

Enregistrez le fournisseur dans votre instance
AuthService:let authService = AuthService() .withGoogleSignIn()
Pour utiliser la connexion via Facebook :
Configurez le SDK Facebook Login pour iOS en suivant les instructions sur le site Meta for Developers. Ignorez la dernière étape, "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 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 APNs pour votre application en suivant les instructions de 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 CIBLES, puis l'onglet Infos et développez la section Types d'URL.
Cliquez sur le bouton +, puis ajoutez votre 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 terminée, votre configuration devrait ressembler à ce qui suit (mais avec vos valeurs spécifiques à l'application) :

Dans le même
AppDelegatedans lequel 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 pour l'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 depuis 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 orientée qui gère l'intégralité du flux d'authentification pour vous. Il s'agit du 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 composant d'image, consultez Ajouter des images à votre projet Xcode.customStringsBundle: utiliser des chaînes personnalisées à partir du Bundle spécifié. Il est utilisé 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, d'authentification multifactorielle, de lien d'e-mail et de validation du numéro de téléphone
- Gestion de l'état de l'authentification : bascule automatiquement entre l'UI d'authentification et votre contenu en fonction de
authService.authenticationState - Contrôle via
isPresented: contrôlez le moment où la feuille d'authentification s'affiche en définissantauthService.isPresented = true/false.
Comportements avisés
La valeur par défaut AuthPickerView est une opinion sur la façon de gérer plusieurs scénarios complexes :
1. Résolution des conflits de compte
En cas de conflit de compte (par exemple, si vous vous connectez avec des identifiants déjà associés à un autre compte), AuthPickerView le gère automatiquement :
- Conflits de mise à niveau anonymes : 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 nouvelles identifiants. - Autres conflits : en cas de conflit 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.
Cela est géré par le AccountConflictModifier appliqué au niveau NavigationStack.
2. Authentification multifacteur (MFA)
Lorsque l'authentification multifacteur est activée dans votre configuration :
- Détecte automatiquement quand l'authentification multifactorielle est requise lors de la connexion
- Affiche les écrans de résolution de l'authentification multifacteur appropriés (SMS ou TOTP)
- Gère les flux d'inscription et de gestion de l'authentification multifactorielle
- Compatible avec les facteurs de mot de passe à usage unique (TOTP) et de code envoyé par SMS
3. Traiter les erreurs
Les vues par défaut incluent la gestion des erreurs intégrée :
- Affiche des messages d'erreur faciles à comprendre dans des boîtes de dialogue d'alerte
- Filtre automatiquement les erreurs gérées en interne (par exemple, les erreurs d'annulation et 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 avec un lien envoyé par e-mail
Lorsque la connexion par lien envoyé par e-mail est configurée :
- Stocke automatiquement l'adresse e-mail dans le stockage de l'application
- Gère la navigation par lien profond depuis un e-mail
- Gère l'intégralité du flux de validation des adresses e-mail
- Prise en charge des mises à niveau pour les utilisateurs anonymes via un lien dans un e-mail
5. Migration automatique des utilisateurs anonymes
Lorsque shouldAutoUpgradeAnonymousUsers est activé :
- Tente automatiquement d'associer les comptes anonymes aux nouveaux identifiants de connexion
- Conserve 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, comme la suppression de comptes, la modification de mots de passe ou la désinscription de facteurs MFA, nécessitent une authentification récente. Lorsque vous utilisez des 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 affichent automatiquement :
Fournisseurs OAuth (Google, Apple, Facebook, Twitter, etc.) : Affichez une alerte demandant à l'utilisateur de confirmer, puis obtenez automatiquement de nouveaux identifiants et effectuez l'opération.
E-mail/Mot de passe : affichez 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 présente une feuille contenant des instructions pour vérifier l'e-mail. L'utilisateur appuie sur le lien contenu dans l'e-mail pour finaliser la réauthentification.
Téléphone : affichez une alerte expliquant qu'une validation est nécessaire, puis présentez une feuille pour la validation du code par SMS.
L'opération fait automatiquement l'objet de plusieurs tentatives après une réauthentification réussie. Aucun code supplémentaire n'est requis lorsque vous utilisez AuthPickerView ou les vues de gestion de compte intégrées (UpdatePasswordView, SignedInView, etc.).
Options avancées : créer des vues d'authentification personnalisées
Si vous avez besoin de contrôler davantage l'UI ou le flux de navigation, vous pouvez créer vos propres vues d'authentification personnalisées tout en tirant parti de 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 d'approches de personnalisation que vous pouvez utiliser.
Approche 1 : Boutons personnalisés avec registerProvider()
Pour contrôler entièrement l'apparence du bouton, 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 comment créer un bouton Twitter personnalisé, par exemple :
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 des vues personnalisées
Vous pouvez utiliser AuthService.renderButtons() et ignorer 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 contrôler entièrement le 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 l'AMF : vérifiez
SignInOutcomepour.mfaRequiredet gérez la résolution de l'AMF 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 lors des opérations d'authentification asynchrone en observant
authService.authenticationState. - Réauthentification : gérez les erreurs de réauthentification pour les opérations sensibles (voir Ré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 détectant 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.) :
Identifiez 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 les 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 vers l'adresse e-mail :
Détectez l'erreur, envoyez un 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 destiné à 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 à Authentification → Méthode 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 pour les développeurs 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)
}
}