
FirebaseUI cho SwiftUI là một thư viện hiện đại, ưu tiên SwiftUI được xây dựng trên Firebase Authentication, cung cấp các quy trình đăng nhập được tạo sẵn cho ứng dụng của bạn.
FirebaseUI cho SwiftUI có những lợi ích sau:
- Giao diện người dùng mặc định có ý kiến: thêm một quy trình đăng nhập hoàn chỉnh bằng
AuthPickerView. - Có thể tuỳ chỉnh: hiển thị các nút mặc định trong bố cục của riêng bạn hoặc tạo một trải nghiệm hoàn toàn tuỳ chỉnh.
- Liên kết tài khoản ẩn danh: bạn có thể chọn nâng cấp người dùng ẩn danh thay vì thay thế họ.
- Quản lý tài khoản: các quy trình tích hợp để đăng ký, khôi phục mật khẩu và quản lý tài khoản.
- Nhiều nhà cung cấp: email/mật khẩu, đường liên kết qua email, xác thực qua điện thoại, Apple, Google, Facebook, Twitter và các nhà cung cấp OAuth2/OIDC tiêu chuẩn.
- Các tính năng xác thực hiện đại: hỗ trợ tích hợp cho tính năng xác thực đa yếu tố (MFA) và API async/await.
Trước khi bắt đầu
Thêm Firebase vào dự án Apple. Hãy nhớ hoàn tất các bước SwiftUI.
Đảm bảo ứng dụng của bạn nhắm đến iOS 17 trở lên.
Lắp đặt
FirebaseUI cho SwiftUI được cung cấp dưới dạng một gói Swift. Để cài đặt gói trong dự án Xcode, hãy làm như sau:
Trong Xcode, hãy nhấp vào File > Add Package Dependencies (Tệp > Thêm phần phụ thuộc của gói).
Nhập URL của gói:
https://github.com/firebase/FirebaseUI-iOSTrong trình đơn Dependency Rule (Quy tắc về phần phụ thuộc), hãy chọn Up to Next Major Version (Lên đến phiên bản chính tiếp theo) và đặt phiên bản tối thiểu thành bản phát hành mới nhất.
Nhấp vào Add Package (Thêm gói), sau đó chọn các thư viện để thêm vào dự án của bạn.
Bạn luôn phải có thư viện sau. SDK này bao gồm các phần phụ thuộc cốt lõi cũng như hỗ trợ tính năng đăng nhập bằng mật khẩu và đăng nhập bằng đường liên kết qua email.
FirebaseAuthSwiftUI
Nếu bạn muốn hỗ trợ các phương thức đăng nhập khác, hãy chọn thêm một hoặc nhiều thư viện sau:
FirebaseAppleSwiftUI(Đăng nhập bằng Apple)FirebaseGoogleSwiftUI(Đăng nhập bằng Google)FirebaseFacebookSwiftUI(Đăng nhập bằng Facebook)FirebasePhoneAuthSwiftUI(Xác thực bằng điện thoại)FirebaseTwitterSwiftUI(Đăng nhập bằng Twitter)FirebaseOAuthSwiftUI(Các nhà cung cấp OAuth và OIDC tiêu chuẩn như GitHub, Microsoft, Yahoo)
Nhấp vào Add Package (Thêm gói) để cài đặt các thư viện đã chọn.
Định cấu hình
AuthServicecủa FirebaseUI trong trình khởi tạoViewcấp cao nhất và truyền dịch vụ đến các khung hiển thị con bằng cách sử dụng môi trường.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) } }
Thiết lập phương thức đăng nhập
Mỗi phương thức đăng nhập được hỗ trợ đều yêu cầu một số bước thiết lập bổ sung. Mở rộng các phần bên dưới và làm theo hướng dẫn để thiết lập từng nhà cung cấp.
Địa chỉ email và mật khẩu
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật nhà cung cấp Email/Mật khẩu.
Đăng ký nhà cung cấp trong phiên bản
AuthServicecủa bạn:let authService = AuthService() .withEmailSignIn()
Xác thực bằng đường liên kết trong email
Cách sử dụng tính năng đăng nhập bằng đường liên kết qua email không cần mật khẩu:
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật Email/Mật khẩu, sau đó bật tính năng đăng nhập bằng đường liên kết qua email. Xin lưu ý rằng bạn phải bật tính năng đăng nhập bằng email hoặc mật khẩu để sử dụng tính năng đăng nhập bằng đường liên kết qua email.
Thêm miền liên kết vào Miền được uỷ quyền.
Định cấu hình
ActionCodeSettings, truyền vàoAuthConfigurationvà đăng ký trình cung cấp: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()Trong cùng một
AppDelegatemà bạn gọiFirebaseApp.configure(), hãy thêm logic vào phương thứcapplication(_:open:options:)trả vềtruekhi URL đã mở là đường liên kết đăng nhập Firebase Authentication. Logic này cho biết rằng đường liên kết đã được FirebaseUI xử lý và không được các trình xử lý đường liên kết khác xử lý.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 } }Nếu bạn tạo các khung hiển thị tuỳ chỉnh, hãy gọi
authService.handleSignInLink(url:)khi đường liên kết mở ứng dụng của bạn.
Apple
Cách sử dụng tính năng Đăng nhập bằng Apple:
Định cấu hình tính năng Đăng nhập bằng Apple:
- Bật tính năng Đăng nhập bằng Apple cho ứng dụng của bạn trên trang Certificates, Identifiers & Profiles (Chứng chỉ, giá trị nhận dạng và hồ sơ) của trang web dành cho nhà phát triển của Apple.
- Liên kết trang web với ứng dụng của bạn như mô tả trong phần đầu tiên của bài viết Định cấu hình tính năng Đăng nhập bằng Apple cho web. Khi được nhắc, hãy đăng ký URL sau đây làm URL trả về:
Bạn có thể lấy mã dự án Firebase trên trang cài đặt bảng điều khiển Firebase. Sau khi hoàn tất, hãy ghi lại mã dịch vụ mới để dùng trong phần tiếp theo.https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- Tạo khoá riêng tư Đăng nhập bằng Apple. Bạn sẽ cần khoá riêng tư và mã khoá mới trong phần tiếp theo.
- Nếu bạn sử dụng bất kỳ tính năng nào của Firebase Authentication để gửi email cho người dùng, bao gồm cả tính năng đăng nhập bằng đường liên kết qua email, xác minh địa chỉ email, thu hồi thay đổi tài khoản và các tính năng khác, hãy thiết lập dịch vụ chuyển tiếp email riêng tư của Apple và đăng ký
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(hoặc miền mẫu email tuỳ chỉnh của bạn) để Apple có thể chuyển tiếp email do Firebase Authentication gửi đến địa chỉ email ẩn danh của Apple.
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật Apple.
- Chỉ định Mã dịch vụ mà bạn đã tạo trong phần trước.
- Trong phần cấu hình luồng mã OAuth, hãy chỉ định Apple Team ID, khoá riêng tư và mã khoá mà bạn đã tạo trong phần trước.
Trong Xcode, hãy mở mục Signing & Capabilities (Ký và khả năng) của trình chỉnh sửa dự án rồi thêm khả năng Sign in with Apple (Đăng nhập bằng Apple).
Đăng ký nhà cung cấp trong phiên bản
AuthServicecủa bạn:let authService = AuthService() .withAppleSignIn()
Cách sử dụng tính năng Đăng nhập bằng Google:
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật nhà cung cấp Google.
Tải một bản sao mới của tệp
GoogleService-Info.plisttrong dự án xuống rồi sao chép tệp đó vào dự án Xcode. Ghi đè mọi phiên bản hiện có bằng phiên bản mới.Thêm giản đồ URL tuỳ chỉnh vào dự án Xcode:
Mở cấu hình dự án: nhấp vào tên dự án trong chế độ xem cây ở bên trái. Chọn ứng dụng của bạn trong mục MỤC TIÊU, sau đó chọn thẻ Thông tin và mở rộng mục Các loại URL.
Nhấp vào nút + rồi thêm một giản đồ URL cho mã nhận dạng ứng dụng khách đảo ngược. Để tìm giá trị này, hãy mở tệp cấu hình
rồi tìm khoáGoogleService-Info.plist REVERSED_CLIENT_ID. Sao chép giá trị của khoá đó rồi dán vào hộp URL Schemes (Lược đồ URL) trên trang cấu hình. Giữ nguyên các trường khác.Sau khi hoàn tất, cấu hình của bạn sẽ có dạng như sau (nhưng có các giá trị dành riêng cho ứng dụng của bạn):

Đăng ký nhà cung cấp trong phiên bản
AuthServicecủa bạn:let authService = AuthService() .withGoogleSignIn()
Cách sử dụng tính năng Đăng nhập bằng Facebook:
Thiết lập SDK Đăng nhập bằng Facebook cho iOS bằng cách làm theo hướng dẫn trên trang web Meta for Developers. Bỏ qua bước cuối cùng "Thêm tính năng Đăng nhập bằng Facebook vào mã của bạn".
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật nhà cung cấp Facebook. Bạn sẽ cần có Mã ứng dụng và Khoá bí mật của ứng dụng Facebook trên trang Meta for Developers.
Đăng ký nhà cung cấp trong phiên bản
AuthServicecủa bạn:let authService = AuthService() .withFacebookSignIn()
Số điện thoại
Cách sử dụng phương thức xác thực bằng điện thoại:
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật nhà cung cấp Điện thoại.
Định cấu hình APNs cho ứng dụng của bạn theo hướng dẫn trong phần Bắt đầu nhận thông báo im lặng.
Thêm giản đồ URL tuỳ chỉnh vào dự án Xcode:
Mở cấu hình dự án: nhấp vào tên dự án trong chế độ xem cây ở bên trái. Chọn ứng dụng của bạn trong mục MỤC TIÊU, sau đó chọn thẻ Thông tin và mở rộng mục Các loại URL.
Nhấp vào nút + rồi thêm Mã ứng dụng đã mã hoá làm một lược đồ URL. Để tìm giá trị này, hãy mở Cài đặt > Chung trong bảng điều khiển Firebase.
Sau khi hoàn tất, cấu hình của bạn sẽ có dạng như sau (nhưng có các giá trị dành riêng cho ứng dụng của bạn):

Trong cùng
AppDelegatemà bạn gọiFirebaseApp.configure(), hãy thêm trình xử lý mã thông báo 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 } }Đăng ký nhà cung cấp trong phiên bản
AuthServicecủa bạn:let authService = AuthService() .withPhoneSignIn()
Twitter (X)
Cách sử dụng tính năng Đăng nhập bằng Twitter:
Tạo thông tin đăng nhập X API bằng cách làm theo hướng dẫn trên trang web X Developers.
Trong phần Bảo mật > Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase, hãy bật nhà cung cấp Twitter. Bạn sẽ cần khoá API và mã bí mật API từ X Developer Console.
Đăng ký nhà cung cấp trong phiên bản
AuthServicecủa bạn:let authService = AuthService() .withTwitterSignIn()
Nhà cung cấp OAuth2 và OIDC tiêu chuẩn
FirebaseUI cũng hỗ trợ các nhà cung cấp OAuth tích hợp sẵn như GitHub, Microsoft và Yahoo, cũng như các nhà cung cấp OIDC tuỳ chỉnh được định cấu hình trong Xác thực Firebase.
let authService = AuthService()
.withOAuthSignIn(OAuthProviderSwift.github())
.withOAuthSignIn(OAuthProviderSwift.microsoft())
.withOAuthSignIn(OAuthProviderSwift.yahoo())
Đối với các nhà cung cấp OIDC tuỳ chỉnh, trước tiên, hãy định cấu hình nhà cung cấp trong Xác thực Firebase, sau đó tạo một OAuthProviderSwift bằng mã nhận dạng nhà cung cấp và cấu hình nút:
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)
Sử dụng khung hiển thị xác thực tạo sẵn
FirebaseUI cho SwiftUI cung cấp AuthPickerView, một giao diện người dùng xác thực được tạo sẵn và có ý kiến riêng, xử lý toàn bộ quy trình xác thực cho bạn. Đây là cách dễ nhất để thêm quy trình xác thực vào ứng dụng của bạn.
Ví dụ
Sau đây là ví dụ về cách sử dụng AuthPickerView, với nhiều nhà cung cấp và lựa chọn cấu hình:
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)
}
}
}
}
Tuỳ chỉnh thông thường
Mặc dù tất cả các tham số AuthConfiguration đều không bắt buộc, nhưng hầu hết các ứng dụng đều tuỳ chỉnh ít nhất các chế độ cài đặt sau:
let configuration = AuthConfiguration(
logo: ImageResource.exampleLogoAsset,
customStringsBundle: .main,
tosUrl: URL(string: "https://example.com/tos"),
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
logo: hình ảnh biểu trưng xuất hiện trên trang xác thực. Để biết thông tin về cách thêm thành phần hình ảnh của riêng bạn, hãy xem phần Thêm hình ảnh vào dự án Xcode.customStringsBundle: sử dụng các chuỗi tuỳ chỉnh từ Bundle đã chỉ định. Thao tác này được dùng để bản địa hoá, nhưng cũng để tuỳ chỉnh các chuỗi mặc định màAuthPickerViewsử dụng. Ví dụ: để đặt thông báo xuất hiện ở đầu trang xác thực, hãy tạoLocalizable.stringsvới nội dung:"Sign in with Firebase" = "Sign in to use ExampleApp";
Nội dung trong khung hiển thị được tạo sẵn
Khi dùng AuthPickerView, bạn sẽ nhận được:
- Trình bày trang tính: Giao diện người dùng xác thực xuất hiện dưới dạng một trang tính phương thức
- Điều hướng tích hợp: Tự động điều hướng giữa các màn hình đăng nhập, khôi phục mật khẩu, xác thực đa yếu tố, liên kết qua email và xác minh qua điện thoại
- Quản lý trạng thái xác thực: Tự động chuyển đổi giữa giao diện người dùng xác thực và nội dung của bạn dựa trên
authService.authenticationState - Kiểm soát thông qua
isPresented: Kiểm soát thời điểm trang xác thực xuất hiện bằng cách đặtauthService.isPresented = true/false
Hành vi có chủ ý
AuthPickerView mặc định có ý kiến về cách xử lý một số trường hợp phức tạp:
1. Giải quyết trường hợp xung đột tài khoản
Khi xảy ra xung đột tài khoản (ví dụ: đăng nhập bằng thông tin đăng nhập đã được liên kết với một tài khoản khác), AuthPickerView sẽ tự động xử lý:
- Xung đột khi nâng cấp ẩn danh: Nếu
shouldAutoUpgradeAnonymousUsersđược bật và xảy ra xung đột trong quá trình nâng cấp ẩn danh, hệ thống sẽ tự động đăng xuất người dùng ẩn danh và đăng nhập bằng thông tin đăng nhập mới. - Các trường hợp xung đột khác: Đối với trường hợp xung đột thông tin đăng nhập giữa các tài khoản không ẩn danh, hệ thống sẽ lưu trữ thông tin đăng nhập đang chờ xử lý và cố gắng liên kết thông tin đó sau khi đăng nhập thành công.
Việc này do AccountConflictModifier xử lý ở cấp NavigationStack.
2. Xác thực đa yếu tố (MFA)
Khi bạn bật MFA trong cấu hình:
- Tự động phát hiện thời điểm cần có MFA trong quá trình đăng nhập
- Hiển thị màn hình giải pháp MFA phù hợp (SMS hoặc TOTP)
- Xử lý quy trình đăng ký và quản lý MFA
- Hỗ trợ cả yếu tố Mật khẩu một lần (OTP) dựa trên SMS và dựa trên thời gian
3. Xử lý lỗi
Các khung hiển thị mặc định có tính năng xử lý lỗi tích hợp:
- Hiện thông báo lỗi thân thiện với người dùng trong hộp thoại cảnh báo
- Tự động lọc bỏ những lỗi được xử lý nội bộ (ví dụ: lỗi huỷ, xung đột được xử lý tự động)
- Sử dụng thông báo lỗi đã bản địa hoá thông qua
StringUtils - Các lỗi được truyền qua khoá môi trường
reportError
4. Đăng nhập bằng đường liên kết trong email
Khi bạn định cấu hình tính năng đăng nhập bằng đường liên kết trong email:
- Tự động lưu trữ địa chỉ email trong bộ nhớ ứng dụng
- Xử lý thao tác điều hướng bằng đường liên kết sâu từ email
- Quản lý toàn bộ quy trình xác minh email
- Hỗ trợ nâng cấp người dùng ẩn danh thông qua đường liên kết trong email
5. Tự động nâng cấp người dùng ẩn danh
Khi shouldAutoUpgradeAnonymousUsers được bật:
- Tự động tìm cách liên kết các tài khoản ẩn danh với thông tin đăng nhập mới
- Lưu giữ dữ liệu người dùng bằng cách nâng cấp thay vì thay thế các phiên ẩn danh
- Xử lý xung đột nâng cấp một cách hiệu quả
6. Xác thực lại trong chế độ xem mặc định
Các thao tác nhạy cảm như xoá tài khoản, cập nhật mật khẩu hoặc huỷ đăng ký các yếu tố MFA đều yêu cầu bạn xác thực gần đây. Khi sử dụng các khung hiển thị mặc định, quá trình xác thực lại sẽ được xử lý tự động dựa trên nhà cung cấp dịch vụ đăng nhập của người dùng.
Khi một thao tác nhạy cảm yêu cầu xác thực lại, các chế độ xem mặc định sẽ tự động:
Nhà cung cấp OAuth (Google, Apple, Facebook, Twitter, v.v.): Hiển thị một cảnh báo yêu cầu người dùng xác nhận, sau đó tự động lấy thông tin xác thực mới và hoàn tất thao tác.
Email/Password (Email/Mật khẩu): Hiển thị một trang yêu cầu người dùng nhập mật khẩu trước khi tiếp tục.
Đường liên kết qua email: Hiện một cảnh báo yêu cầu gửi email xác minh, sau đó trình bày một trang có hướng dẫn kiểm tra email. Người dùng nhấn vào đường liên kết trong email để hoàn tất quá trình xác thực lại.
Điện thoại: Hiện một cảnh báo giải thích rằng cần xác minh, sau đó trình bày một bảng để xác minh mã qua SMS.
Thao tác này sẽ tự động thử lại sau khi xác thực lại thành công. Bạn không cần thêm mã khi sử dụng AuthPickerView hoặc các khung hiển thị quản lý tài khoản tích hợp (UpdatePasswordView, SignedInView, v.v.).
Nâng cao: Xây dựng khung hiển thị xác thực tuỳ chỉnh
Nếu cần kiểm soát nhiều hơn đối với giao diện người dùng hoặc quy trình điều hướng, bạn có thể tạo các khung hiển thị xác thực tuỳ chỉnh của riêng mình trong khi vẫn tận dụng AuthService cho logic xác thực.
Bạn có thể kết hợp các phần tử của FirebaseUI với logic tuỳ chỉnh theo nhiều cách. Các phần sau đây chứa ví dụ về một số phương pháp tuỳ chỉnh mà bạn có thể sử dụng.
Cách 1: Nút tuỳ chỉnh có registerProvider()
Để kiểm soát hoàn toàn giao diện nút, bạn có thể tạo chế độ triển khai AuthProviderUI tuỳ chỉnh của riêng mình để bao bọc mọi nhà cung cấp và trả về khung hiển thị nút tuỳ chỉnh.
Tạo giao diện người dùng của trình cung cấp tuỳ chỉnh
Sau đây là ví dụ về cách tạo một nút Twitter tuỳ chỉnh:
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")
}
}
}
}
}
Ví dụ về nút tuỳ chỉnh được đơn giản hoá
Bạn cũng có thể tạo các nút tuỳ chỉnh đơn giản hơn cho bất kỳ nhà cung cấp nào:
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)
}
}
Phương pháp này áp dụng cho tất cả nhà cung cấp: Google, Apple, Twitter, Facebook, Điện thoại và nhà cung cấp OAuth. Bạn chỉ cần tạo khung hiển thị nút tuỳ chỉnh và gói khung hiển thị đó trong một lớp tuân thủ AuthProviderUI.
Cách tiếp cận 2: Nút mặc định có khung hiển thị tuỳ chỉnh
Bạn có thể sử dụng AuthService.renderButtons() và bỏ qua AuthPickerView để hiển thị các nút xác thực mặc định trong khi cung cấp bố cục và chế độ điều hướng của riêng bạn:
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)
}
}
Cách tiếp cận 3: Khung hiển thị tuỳ chỉnh có chế độ điều hướng tuỳ chỉnh
Để có toàn quyền kiểm soát toàn bộ quy trình, bạn có thể bỏ qua AuthPickerView và tạo hệ thống điều hướng của riêng mình:
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)
}
}
}
Những điểm quan trọng cần lưu ý đối với khung hiển thị tuỳ chỉnh
Khi tạo chế độ xem tuỳ chỉnh, bạn cần tự xử lý một số việc mà AuthPickerView tự động xử lý:
- Xung đột tài khoản: Triển khai chiến lược giải quyết xung đột của riêng bạn bằng cách sử dụng
AuthServiceError.accountConflict - Xử lý MFA: Kiểm tra
SignInOutcomeđể biết.mfaRequiredvà xử lý độ phân giải MFA theo cách thủ công - Nâng cấp người dùng ẩn danh: Xử lý việc liên kết tài khoản ẩn danh nếu
shouldAutoUpgradeAnonymousUsersđược bật - Trạng thái điều hướng: Quản lý hoạt động điều hướng giữa các màn hình xác thực (xác minh qua điện thoại, khôi phục mật khẩu, v.v.)
- Trạng thái tải: Hiện chỉ báo tải trong các thao tác xác thực không đồng bộ bằng cách quan sát
authService.authenticationState - Xác thực lại: Xử lý lỗi xác thực lại đối với các thao tác nhạy cảm (xem phần Xác thực lại trong Chế độ xem tuỳ chỉnh bên dưới)
Xác thực lại trong chế độ xem tuỳ chỉnh
Khi tạo khung hiển thị tuỳ chỉnh, hãy xử lý việc xác thực lại bằng cách nắm bắt các lỗi cụ thể và triển khai quy trình của riêng bạn. Các thao tác nhạy cảm sẽ gửi 4 loại lỗi xác thực lại, mỗi loại chứa thông tin về bối cảnh.
Mẫu triển khai
Nhà cung cấp OAuth (Google, Apple, Facebook, Twitter, v.v.):
Bắt lỗi và gọi reauthenticate(context:) để tự động xử lý quy trình 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/Mật khẩu:
Bắt lỗi, nhắc nhập mật khẩu, tạo thông tin xác thực và gọi 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
}
}
Điện thoại:
Bắt lỗi, xác minh điện thoại, tạo thông tin xác thực và gọi 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
}
}
Đường liên kết qua email:
Bắt lỗi, gửi email xác minh và xử lý URL đến:
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
}
}
Tất cả các đối tượng bối cảnh xác thực lại đều có một thuộc tính .displayMessage cho văn bản mà người dùng nhìn thấy.
Nhà cung cấp OAuth tuỳ chỉnh
Bạn có thể tạo nhà cung cấp OAuth tuỳ chỉnh cho các dịch vụ ngoài những dịch vụ tích hợp sẵn:
⚠️ Quan trọng: Bạn phải định cấu hình nhà cung cấp OIDC (OpenID Connect) trong phần cài đặt Xác thực của dự án Firebase thì mới có thể sử dụng. Trong Bảng điều khiển Firebase, hãy chuyển đến Xác thực → Phương thức đăng nhập rồi thêm nhà cung cấp OIDC bằng thông tin xác thực bắt buộc (Mã ứng dụng khách, Khoá bí mật của ứng dụng khách, URL của tổ chức phát hành). Bạn cũng phải đăng ký URI chuyển hướng OAuth do Firebase cung cấp trong bảng điều khiển dành cho nhà phát triển của nhà cung cấp. Hãy xem tài liệu về OIDC của Firebase để biết hướng dẫn chi tiết về cách thiết lập.
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)
}
}