
適用於 SwiftUI 的 FirebaseUI 是以 Firebase Authentication 為基礎建構的現代化程式庫,以 SwiftUI 為優先考量,可為應用程式提供預先建構的登入流程。
SwiftUI 適用的 FirebaseUI 具有下列優點:
- 預設 UI:使用
AuthPickerView新增完整的登入流程。 - 可自訂:在自己的版面配置中算繪預設按鈕,或打造完全自訂的體驗。
- 匿名帳戶連結:選擇升級匿名使用者,而非取代。
- 帳戶管理:內建註冊、密碼復原和帳戶管理流程。
- 多個提供者:電子郵件/密碼、電子郵件連結、電話驗證、Apple、Google、Facebook、Twitter,以及標準 OAuth2/OIDC 提供者。
- 新式驗證功能:內建支援多重驗證 (MFA) 和 async/await API。
事前準備
將 Firebase 新增至 Apple 專案。請務必完成 SwiftUI 步驟。
確認應用程式以 iOS 17 以上版本為目標。
安裝
SwiftUI 適用的 FirebaseUI 以 Swift 套件的形式提供。如要在 Xcode 專案中安裝套件,請按照下列步驟操作:
在 Xcode 中,依序點選「File」>「Add Package Dependencies」。
輸入套件網址:
https://github.com/firebase/FirebaseUI-iOS在「Dependency Rule」選單中,選取「Up to Next Major Version」,並將最低版本設為最新版本。
按一下「Add Package」(新增套件),然後選取要新增至專案的程式庫。
您一律需要下列程式庫。其中包含核心依附元件,以及電子郵件/密碼登入和電子郵件連結登入的支援功能。
FirebaseAuthSwiftUI
如要支援其他登入方法,請選取下列一或多個程式庫:
FirebaseAppleSwiftUI(使用 Apple 帳戶登入)FirebaseGoogleSwiftUI(使用 Google 帳戶登入)FirebaseFacebookSwiftUI(使用 Facebook 帳戶登入)FirebasePhoneAuthSwiftUI(手機驗證)FirebaseTwitterSwiftUI(使用 Twitter 帳戶登入)FirebaseOAuthSwiftUI(標準 OAuth 和 OIDC 提供者,例如 GitHub、Microsoft、Yahoo)
按一下「新增套件」,安裝所選程式庫。
在頂層的初始設定中設定 FirebaseUI 的
AuthService,View並使用環境將服務傳遞至子檢視畫面。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) } }
設定登入方式
每種支援的登入方法都需要額外的設定步驟。 展開下方各節並按照操作說明設定個別供應商。
電子郵件地址和密碼
透過電子郵件連結驗證
如要使用不需要密碼的電子郵件連結登入方式:
在 Firebase 控制台的「安全性」>「驗證」>「登入方式」部分,啟用「電子郵件/密碼」,然後啟用電子郵件連結登入功能。請注意,如要使用電子郵件連結登入功能,必須先啟用電子郵件或密碼登入功能。
將連結網域新增至「已授權網域」。
設定
ActionCodeSettings,將其傳遞至AuthConfiguration並註冊提供者: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()在呼叫
FirebaseApp.configure()的相同AppDelegate中,將邏輯新增至application(_:open:options:)方法,在開啟的網址是 Firebase Authentication 登入連結時傳回true。這項邏輯表示連結是由 FirebaseUI 處理,不應由其他連結處理常式處理。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 } }如果您建立自訂檢視畫面,請在連結開啟應用程式時呼叫
authService.handleSignInLink(url:)。
Apple
如要使用「使用 Apple 帳戶登入」功能,請按照下列步驟操作:
設定「使用 Apple 帳戶登入」:
- 在 Apple 開發人員網站的「Certificates, Identifiers & Profiles」頁面,為應用程式啟用「使用 Apple 登入」功能。
- 按照「為網站設定『使用 Apple 登入』功能」一文第一節的說明,將網站與應用程式建立關聯。系統提示時,請將下列網址註冊為返回網址:
您可以在Firebase控制台設定頁面取得 Firebase 專案 ID。 完成後,請記下新的服務 ID,下節會用到。https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- 建立「使用 Apple 帳戶登入」私密金鑰。 下一節會需要新的私密金鑰和金鑰 ID。
- 如果您使用 Firebase Authentication 的任何功能傳送電子郵件給使用者,包括電子郵件連結登入、電子郵件地址驗證、帳戶變更撤銷等,請設定 Apple 私人電子郵件轉發服務,並註冊
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(或自訂電子郵件範本網域),這樣 Apple 就能將 Firebase Authentication 傳送的電子郵件轉發至匿名 Apple 電子郵件地址。
在 Firebase 控制台的「安全性」>「驗證」>「登入方式」部分,啟用「Apple」。
- 指定您在上一節建立的服務 ID。
- 在「OAuth code flow configuration」(OAuth 程式碼流程設定) 部分,指定您的 Apple 團隊 ID,以及您在上一節中建立的私密金鑰和金鑰 ID。
在 Xcode 中開啟專案編輯器的「Signing & Capabilities」(簽署與功能) 區段,然後新增「Sign in with Apple」(使用 Apple 登入) 功能。
在
AuthService執行個體中註冊供應商:let authService = AuthService() .withAppleSignIn()
如要使用 Google 登入,請按照下列步驟操作:
下載專案的
GoogleService-Info.plist檔案副本,並複製到 Xcode 專案。覆寫所有現有版本。在 Xcode 專案中新增自訂網址架構:
開啟專案設定:按一下左側樹狀檢視畫面中的專案名稱。在「目標」部分選取應用程式,然後選取「資訊」分頁標籤,並展開「網址類型」部分。
按一下「+」按鈕,然後為反向用戶端 ID 新增網址架構。如要找出這個值,請開啟
設定檔,然後尋找GoogleService-Info.plist REVERSED_CLIENT_ID鍵。複製該金鑰的值,然後貼到設定頁面的「URL Schemes」(網址架構) 方塊中。其他欄位則維持不變。完成後,您的設定應如下所示 (但會包含應用程式專屬值):

在
AuthService執行個體中註冊供應商:let authService = AuthService() .withGoogleSignIn()
如要使用 Facebook 登入功能,請按照下列步驟操作:
請按照 Meta for Developers 網站上的操作說明,設定 Facebook Login for iOS SDK。略過最後一個步驟「將 Facebook 登入功能新增至程式碼」。
在 Firebase 控制台的「安全性」>「驗證」>「登入方式」部分,啟用「Facebook」供應商。您需要 Meta for Developers 網站提供的 Facebook 應用程式 ID 和應用程式密鑰。
在
AuthService執行個體中註冊供應商:let authService = AuthService() .withFacebookSignIn()
電話號碼
如要使用電話驗證,請按照下列步驟操作:
按照「開始接收無聲通知」一節的說明,為應用程式設定 APNs。
在 Xcode 專案中新增自訂網址架構:
在呼叫
FirebaseApp.configure()的相同AppDelegate中,新增 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 } }在
AuthService執行個體中註冊供應商:let authService = AuthService() .withPhoneSignIn()
Twitter (X)
如要使用 Twitter 登入功能,請按照下列步驟操作:
按照 X 開發人員網站上的操作說明,產生 X API 憑證。
在 Firebase 控制台的「安全性」>「驗證」>「登入方式」部分,啟用「Twitter」供應商。您需要 X 開發人員控制台的 API 金鑰和 API 密鑰。
在
AuthService執行個體中註冊供應商:let authService = AuthService() .withTwitterSignIn()
標準 OAuth2 和 OIDC 供應商
FirebaseUI 也支援內建的 OAuth 提供者,例如 GitHub、Microsoft 和 Yahoo,以及在 Firebase 驗證中設定的自訂 OIDC 提供者。
let authService = AuthService()
.withOAuthSignIn(OAuthProviderSwift.github())
.withOAuthSignIn(OAuthProviderSwift.microsoft())
.withOAuthSignIn(OAuthProviderSwift.yahoo())
如果是自訂 OIDC 提供者,請先在 Firebase 驗證中設定提供者,然後使用提供者 ID 和按鈕設定建立 OAuthProviderSwift:
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)
使用預先建構的驗證檢視畫面
SwiftUI 適用的 FirebaseUI 提供 AuthPickerView,這是一個預先建構的驗證 UI,可處理整個驗證流程。這是為應用程式新增驗證功能最簡單的方法。
範例
以下是 AuthPickerView 的使用範例,其中包含多個供應商和設定選項:
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)
}
}
}
}
常見自訂項目
雖然所有 AuthConfiguration 參數都是選用,但大多數應用程式至少會自訂下列設定:
let configuration = AuthConfiguration(
logo: ImageResource.exampleLogoAsset,
customStringsBundle: .main,
tosUrl: URL(string: "https://example.com/tos"),
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
logo:顯示在驗證表單上的標誌圖片。 如要瞭解如何加入自己的圖片素材資源,請參閱「將圖片新增至 Xcode 專案」。customStringsBundle:使用指定 Bundle 中的自訂字串。這項屬性可用於本地化,也能自訂AuthPickerView使用的預設字串。舉例來說,如要設定顯示在驗證表單頂端的訊息,請使用下列內容建立Localizable.strings:"Sign in with Firebase" = "Sign in to use ExampleApp";
預建檢視畫面包含哪些內容
使用 AuthPickerView 可享有以下福利:
- Sheet Presentation:驗證 UI 會以模式對話方塊的形式顯示
- 內建導覽:自動在登入、密碼救援、多重驗證、電子郵件連結和電話號碼驗證畫面之間導覽
- 驗證狀態管理:根據
authService.authenticationState自動在驗證 UI 和內容之間切換 - 透過
isPresented控制:設定authService.isPresented = true/false,控制何時顯示驗證表單
條理明確的行為
預設 AuthPickerView 會針對如何處理多種複雜情境提供建議:
1. 解決帳戶衝突問題
發生帳戶衝突時 (例如使用已連結至其他帳戶的憑證登入),AuthPickerView 會自動處理:
- 匿名升級衝突:如果啟用
shouldAutoUpgradeAnonymousUsers,且匿名升級期間發生衝突,系統會自動登出匿名使用者,並使用新憑證登入。 - 其他衝突:如果非匿名帳戶之間發生憑證衝突,系統會儲存待處理的憑證,並在成功登入後嘗試連結。
這是由 NavigationStack 層級套用的 AccountConflictModifier 處理。
2. 多重驗證 (MFA)
在設定中啟用 MFA 後:
- 登入時自動偵測是否需要多重驗證
- 顯示適當的 MFA 解決畫面 (簡訊或 TOTP)
- 處理多重驗證註冊和管理流程
- 支援簡訊和限時動態密碼 (TOTP) 因素
3. 處理錯誤
預設檢視畫面包含內建錯誤處理機制:
- 在快訊對話方塊中顯示清楚易懂的錯誤訊息
- 自動篩除內部處理的錯誤 (例如取消錯誤、自動處理的衝突)
- 透過
StringUtils使用本地化錯誤訊息 - 錯誤會透過
reportError環境金鑰傳播
4. 內含登入連結的電子郵件
設定電子郵件連結登入後:
- 自動將電子郵件地址儲存在應用程式儲存空間中
- 處理電子郵件中的深層連結導覽
- 管理完整的電子郵件驗證流程
- 支援透過電子郵件連結升級匿名使用者
5. 匿名使用者自動升級
啟用「shouldAutoUpgradeAnonymousUsers」後:
- 自動嘗試將匿名帳戶連結至新的登入憑證
- 升級匿名工作階段,而非取代,以保留使用者資料
- 妥善處理升級衝突
6. 預設檢視畫面中的重新驗證
執行刪除帳戶、更新密碼或取消註冊多重驗證因素等敏感操作時,必須先完成驗證。使用預設檢視畫面時,系統會根據使用者的登入供應商自動處理重新驗證。
當敏感作業需要重新驗證時,預設檢視畫面會自動執行下列操作:
OAuth 提供者 (Google、Apple、Facebook、Twitter 等):顯示要求使用者確認的快訊,然後自動取得新憑證並完成作業。
電子郵件地址/密碼:顯示提示,要求使用者先輸入密碼再繼續。
電子郵件連結:顯示要求傳送驗證電子郵件的快訊,然後顯示內含電子郵件檢查指示的頁面。使用者輕觸電子郵件中的連結,完成重新驗證。
電話:顯示說明需要驗證的快訊,然後顯示簡訊驗證碼的表單。
重新驗證成功後,系統會自動重試作業。使用 AuthPickerView 或內建帳戶管理檢視畫面 (UpdatePasswordView、SignedInView 等) 時,不需要額外程式碼。
進階:建構自訂驗證檢視畫面
如要進一步控管 UI 或導覽流程,您可以自行建立自訂驗證檢視畫面,同時仍使用 AuthService 進行驗證邏輯。
您可以透過多種方式,將 FirebaseUI 元素與自訂邏輯混合使用。以下章節提供幾個自訂方法的範例。
做法 1:使用 registerProvider() 的自訂按鈕
如要完全掌控按鈕外觀,可以建立自己的自訂 AuthProviderUI 實作項目,包裝任何供應商並傳回自訂按鈕檢視畫面。
建立自訂供應商 UI
以下舉例說明如何建立自訂的 Twitter 按鈕:
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")
}
}
}
}
}
簡化自訂按鈕範例
您也可以為任何供應商建立較簡單的自訂按鈕:
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)
}
}
這個方法適用於所有供應商:Google、Apple、Twitter、Facebook、電話和 OAuth 供應商。只要建立自訂按鈕檢視區塊,並將其包裝在符合 AuthProviderUI 的類別中即可。
方法 2:使用預設按鈕和自訂檢視畫面
您可以透過 AuthService.renderButtons() 和略過 AuthPickerView,在提供自己的版面配置和導覽時,算繪預設的驗證按鈕:
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)
}
}
方法 3:使用自訂導覽的自訂檢視畫面
如要全面掌控整個流程,可以略過 AuthPickerView 並建構自己的導覽系統:
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)
}
}
}
自訂檢視畫面的重要注意事項
建構自訂檢視區塊時,您需要自行處理 AuthPickerView 會自動處理的幾件事:
- 帳戶衝突:使用
AuthServiceError.accountConflict實作您自己的衝突解決策略 - MFA 處理:檢查
SignInOutcome是否為.mfaRequired,並手動處理 MFA 解決方案 - 匿名使用者升級:如果啟用
shouldAutoUpgradeAnonymousUsers,請處理匿名帳戶的連結作業 - 導覽狀態:管理不同驗證畫面 (電話號碼驗證、密碼復原等) 間的導覽
- 載入狀態:在非同步驗證作業期間,透過觀察
authService.authenticationState顯示載入指標 - 重新驗證:處理敏感作業的重新驗證錯誤 (請參閱下方的「自訂檢視區塊中的重新驗證」)
自訂檢視畫面中的重新驗證
建構自訂檢視畫面時,請擷取特定錯誤並實作自己的流程,以處理重新驗證作業。敏感性作業會擲回四種重新驗證錯誤,每種錯誤都包含內容資訊。
實作模式
OAuth 供應商 (Google、Apple、Facebook、Twitter 等):
擷取錯誤並呼叫 reauthenticate(context:),系統會自動處理 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
}
}
電子郵件/密碼:
擷取錯誤、提示輸入密碼、建立憑證,然後呼叫 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
}
}
電話:
擷取錯誤、驗證電話、建立憑證,然後呼叫 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
}
}
電子郵件連結:
擷取錯誤、傳送驗證電子郵件,並處理傳入的網址:
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
}
}
所有重新驗證內容物件都包含使用者可見文字的 .displayMessage 屬性。
自訂 OAuth 供應商
您可以為內建服務以外的服務建立自訂 OAuth 提供者:
⚠️ 重要事項:必須先在 Firebase 專案的「驗證」設定中設定 OIDC (OpenID Connect) 提供者,才能使用這些提供者。在 Firebase 控制台中,前往「Authentication」→「Sign-in method」,然後使用必要憑證 (用戶端 ID、用戶端密鑰、核發者網址) 新增 OIDC 供應商。您也必須在供應商的開發人員控制台中,註冊 Firebase 提供的 OAuth 重新導向 URI。如需詳細設定說明,請參閱 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)
}
}