
FirebaseUI สำหรับ SwiftUI เป็นไลบรารีที่ทันสมัยและใช้ SwiftUI เป็นอันดับแรก ซึ่งสร้างขึ้นบน Firebase Authentication ที่มี โฟลว์การลงชื่อเข้าใช้ที่สร้างไว้ล่วงหน้าสำหรับแอปของคุณ
FirebaseUI สำหรับ SwiftUI มีประโยชน์ดังนี้
- UI เริ่มต้นที่กำหนด: เพิ่มขั้นตอนการลงชื่อเข้าใช้ที่สมบูรณ์ด้วย
AuthPickerView - ปรับแต่งได้: แสดงปุ่มเริ่มต้นในเลย์เอาต์ของคุณเอง หรือสร้างประสบการณ์การใช้งานที่กำหนดเองทั้งหมด
- การลิงก์บัญชีที่ไม่ระบุชื่อ: อัปเกรดผู้ใช้ที่ไม่ระบุชื่อแทนการแทนที่ (ไม่บังคับ)
- การจัดการบัญชี: ขั้นตอนในตัวสำหรับการลงชื่อสมัครใช้ การกู้คืนรหัสผ่าน และการจัดการบัญชี
- ผู้ให้บริการหลายราย: อีเมล/รหัสผ่าน ลิงก์อีเมล การตรวจสอบสิทธิ์ทางโทรศัพท์ Apple, Google, Facebook, Twitter และผู้ให้บริการ OAuth2/OIDC มาตรฐาน
- ฟีเจอร์การตรวจสอบสิทธิ์สมัยใหม่: รองรับการตรวจสอบสิทธิ์แบบหลายปัจจัย (MFA) และ API แบบอะซิงโครนัส/รอ
ก่อนเริ่มต้น
เพิ่ม Firebase ในโปรเจ็กต์ Apple อย่าลืมทำตาม ขั้นตอน SwiftUI
ตรวจสอบว่าแอปกำหนดเป้าหมายเป็น iOS 17 ขึ้นไป
การติดตั้ง
FirebaseUI สำหรับ SwiftUI มีให้ใช้งานเป็นแพ็กเกจ Swift หากต้องการติดตั้งแพ็กเกจในโปรเจ็กต์ Xcode ให้ทำดังนี้
ใน Xcode ให้คลิกไฟล์ > เพิ่มการขึ้นต่อกันของแพ็กเกจ
ป้อน URL ของแพ็กเกจ
https://github.com/firebase/FirebaseUI-iOSในเมนูกฎการขึ้นต่อกัน ให้เลือกสูงสุดถึงเวอร์ชันหลักถัดไป แล้วตั้งค่า เวอร์ชันขั้นต่ำเป็น รุ่นล่าสุด
คลิกเพิ่มแพ็กเกจ แล้วเลือกไลบรารีที่จะเพิ่มลงในโปรเจ็กต์
ต้องมีไลบรารีต่อไปนี้เสมอ ซึ่งรวมถึงการอ้างอิงหลัก ตลอดจนการรองรับการลงชื่อเข้าใช้ด้วยอีเมลและรหัสผ่าน รวมถึงการลงชื่อเข้าใช้ด้วยลิงก์อีเมล
FirebaseAuthSwiftUI
หากต้องการรองรับวิธีการลงชื่อเข้าใช้อื่นๆ ให้เลือกไลบรารีต่อไปนี้อย่างน้อย 1 รายการด้วย
FirebaseAppleSwiftUI(ลงชื่อเข้าใช้ด้วย Apple)FirebaseGoogleSwiftUI(ลงชื่อเข้าใช้ด้วย Google)FirebaseFacebookSwiftUI(ลงชื่อเข้าใช้ด้วย Facebook)FirebasePhoneAuthSwiftUI(การตรวจสอบสิทธิ์ทางโทรศัพท์)FirebaseTwitterSwiftUI(ลงชื่อเข้าใช้ด้วย Twitter)FirebaseOAuthSwiftUI(ผู้ให้บริการ OAuth และ OIDC มาตรฐาน เช่น GitHub, Microsoft, Yahoo)
คลิกเพิ่มแพ็กเกจเพื่อติดตั้งไลบรารีที่เลือก
กำหนดค่า
AuthServiceของ FirebaseUI ในตัวเริ่มต้นของ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คอนโซล ให้เปิดใช้ผู้ให้บริการอีเมล/รหัสผ่าน
ลงทะเบียนผู้ให้บริการในอินสแตนซ์
AuthServiceดังนี้let authService = AuthService() .withEmailSignIn()
การตรวจสอบสิทธิ์ลิงก์ในอีเมล
วิธีใช้การลงชื่อเข้าใช้ด้วยลิงก์อีเมลแบบไม่ต้องใช้รหัสผ่าน
จากส่วนความปลอดภัย > การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของคอนโซล 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()ใน
AppDelegateเดียวกันกับที่เรียกใช้FirebaseApp.configure()ให้เพิ่ม ตรรกะลงในเมธอดapplication(_:open:options:)ที่แสดงผลtrueเมื่อ URL ที่เปิดเป็นลิงก์ลงชื่อเข้าใช้ Firebase Authentication ตรรกะนี้ บ่งชี้ว่า 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 สำหรับแอปในหน้าใบรับรอง ตัวระบุ และโปรไฟล์ ของเว็บไซต์นักพัฒนาแอปของ Apple
- เชื่อมโยงเว็บไซต์กับแอปตามที่อธิบายไว้ในส่วนแรกของกำหนดค่าการลงชื่อเข้าใช้ด้วย Apple สำหรับเว็บ เมื่อได้รับข้อความแจ้ง ให้ลงทะเบียน
URL ต่อไปนี้เป็น URL เปลี่ยนเส้นทางกลับ
คุณดูรหัสโปรเจ็กต์ Firebase ได้ในหน้าการตั้งค่าคอนโซลFirebase เมื่อเสร็จแล้ว ให้จดรหัสบริการใหม่ ซึ่งคุณจะต้องใช้ใน ส่วนถัดไปhttps://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
- สร้างคีย์ส่วนตัวสำหรับลงชื่อเข้าใช้ด้วย Apple คุณจะต้องใช้คีย์ส่วนตัวและรหัสคีย์ใหม่ในส่วนถัดไป
- หากคุณใช้ฟีเจอร์ของ Firebase Authentication ที่ส่งอีเมลถึงผู้ใช้
รวมถึงการลงชื่อเข้าใช้ด้วยลิงก์อีเมล การยืนยันอีเมล การเพิกถอนการเปลี่ยนแปลงบัญชี
และอื่นๆ ให้กำหนดค่าบริการส่งต่ออีเมลส่วนตัวของ Apple
และลงทะเบียน
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(หรือโดเมนเทมเพลตอีเมลที่กำหนดเอง) เพื่อให้ Apple ส่งต่ออีเมลที่ Firebase Authentication ส่งไปยังอีเมล Apple ที่ไม่ระบุตัวตนได้
จากส่วนความปลอดภัย > การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของคอนโซล Firebase ให้เปิดใช้ Apple
- ระบุรหัสบริการที่คุณสร้างไว้ในส่วนก่อนหน้า
- ในส่วนการกำหนดค่าโฟลว์ของรหัส OAuth ให้ระบุรหัสทีม Apple คีย์ส่วนตัว และรหัสคีย์ที่คุณสร้างไว้ในส่วนก่อนหน้า
ใน Xcode ให้เปิดส่วนการลงนามและความสามารถของโปรแกรมแก้ไขโปรเจ็กต์ แล้วเพิ่มความสามารถลงชื่อเข้าใช้ด้วย Apple
ลงทะเบียนผู้ให้บริการในอินสแตนซ์
AuthServiceดังนี้let authService = AuthService() .withAppleSignIn()
วิธีใช้การลงชื่อเข้าใช้ด้วย Google
จากส่วนความปลอดภัย > การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของคอนโซล Firebase ให้เปิดใช้ผู้ให้บริการ Google
ดาวน์โหลดสำเนาใหม่ของไฟล์
GoogleService-Info.plistของโปรเจ็กต์ แล้วคัดลอกไปยังโปรเจ็กต์ Xcode เขียนทับเวอร์ชันที่มีอยู่ด้วยเวอร์ชันใหม่เพิ่มรูปแบบ URL ที่กำหนดเองลงในโปรเจ็กต์ Xcode โดยทำดังนี้
เปิดการกำหนดค่าโปรเจ็กต์โดยคลิกชื่อโปรเจ็กต์ในมุมมองแบบทรีทางด้านซ้าย เลือกแอปจากส่วนเป้าหมาย จากนั้น เลือกแท็บข้อมูล แล้วขยายส่วนประเภท URL
คลิกปุ่ม + แล้วเพิ่มรูปแบบ URL สำหรับรหัสไคลเอ็นต์ที่กลับด้าน หากต้องการดูค่านี้ ให้เปิด
ไฟล์การกำหนดค่า แล้วมองหาคีย์GoogleService-Info.plist REVERSED_CLIENT_IDคัดลอกค่าของคีย์นั้น แล้ววางลงในช่องรูปแบบ URL ในหน้าการกำหนดค่า ไม่ต้องแก้ไขฟิลด์อื่นๆเมื่อเสร็จแล้ว การกำหนดค่าควรมีลักษณะคล้ายกับ ต่อไปนี้ (แต่มีค่าเฉพาะแอปพลิเคชันของคุณ)

ลงทะเบียนผู้ให้บริการในอินสแตนซ์
AuthServiceดังนี้let authService = AuthService() .withGoogleSignIn()
วิธีใช้การเข้าสู่ระบบด้วย Facebook
ตั้งค่า Facebook Login สำหรับ iOS SDK โดยทำตามวิธีการ ในเว็บไซต์ Meta for Developers ข้ามขั้นตอนสุดท้าย "เพิ่มการเข้าสู่ระบบด้วย Facebook ลงในโค้ด"
จากส่วนความปลอดภัย > การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของคอนโซล Firebase ให้เปิดใช้ผู้ให้บริการ Facebook คุณจะต้องใช้รหัสแอป Facebook และข้อมูลลับของแอปจากเว็บไซต์ Meta for Developers
ลงทะเบียนผู้ให้บริการในอินสแตนซ์
AuthServiceดังนี้let authService = AuthService() .withFacebookSignIn()
หมายเลขโทรศัพท์
วิธีใช้การตรวจสอบสิทธิ์ทางโทรศัพท์
จากส่วนความปลอดภัย > การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของFirebaseคอนโซล ให้เปิดใช้ผู้ให้บริการโทรศัพท์
กำหนดค่า APNs สำหรับแอปตามที่ระบุไว้ในส่วนเริ่มรับการแจ้งเตือนแบบเงียบ
เพิ่มรูปแบบ URL ที่กำหนดเองลงในโปรเจ็กต์ Xcode โดยทำดังนี้
เปิดการกำหนดค่าโปรเจ็กต์โดยคลิกชื่อโปรเจ็กต์ในมุมมองแบบทรีทางด้านซ้าย เลือกแอปจากส่วนเป้าหมาย จากนั้น เลือกแท็บข้อมูล แล้วขยายส่วนประเภท URL
คลิกปุ่ม + แล้วเพิ่มรหัสแอปที่เข้ารหัสเป็นรูปแบบ URL หากต้องการดูค่านี้ ให้เปิดการตั้งค่า > ทั่วไป ในคอนโซล Firebase
เมื่อเสร็จแล้ว การกำหนดค่าควรมีลักษณะคล้ายกับ ต่อไปนี้ (แต่มีค่าเฉพาะแอปพลิเคชันของคุณ)

ใน
AppDelegateเดียวกันกับที่คุณเรียกFirebaseApp.configure()ให้เพิ่ม ตัวแฮนเดิลโทเค็น 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 API โดยทำตามวิธีการใน เว็บไซต์นักพัฒนาซอฟต์แวร์ X
จากส่วนความปลอดภัย > การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของFirebaseคอนโซล ให้เปิดใช้ผู้ให้บริการ Twitter คุณจะต้องใช้คีย์ API และ API Secret จากคอนโซลนักพัฒนาซอฟต์แวร์ของ X
ลงทะเบียนผู้ให้บริการในอินสแตนซ์
AuthServiceดังนี้let authService = AuthService() .withTwitterSignIn()
ผู้ให้บริการ OAuth2 และ OIDC มาตรฐาน
นอกจากนี้ FirebaseUI ยังรองรับผู้ให้บริการ OAuth ในตัว เช่น GitHub, Microsoft และ Yahoo รวมถึงผู้ให้บริการ OIDC ที่กำหนดเองซึ่งกำหนดค่าไว้ในการตรวจสอบสิทธิ์ Firebase
let authService = AuthService()
.withOAuthSignIn(OAuthProviderSwift.github())
.withOAuthSignIn(OAuthProviderSwift.microsoft())
.withOAuthSignIn(OAuthProviderSwift.yahoo())
สำหรับผู้ให้บริการ OIDC ที่กำหนดเอง ให้กำหนดค่าผู้ให้บริการใน Firebase
Authentication ก่อน จากนั้นสร้าง 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)
การใช้มุมมองการตรวจสอบสิทธิ์ที่สร้างไว้ล่วงหน้า
FirebaseUI สำหรับ SwiftUI มี 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: รูปภาพโลโก้ที่แสดงในเอกสารการตรวจสอบสิทธิ์ ดูข้อมูลเกี่ยวกับการรวมชิ้นงานรูปภาพของคุณเองได้ที่ การเพิ่มรูปภาพลงในโปรเจ็กต์ XcodecustomStringsBundle: ใช้สตริงที่กำหนดเองจาก Bundle ที่ระบุ ซึ่งใช้สำหรับการแปลภาษาท้องถิ่น รวมถึงใช้ปรับแต่งสตริงเริ่มต้นที่AuthPickerViewใช้ด้วย เช่น หากต้องการตั้งค่าข้อความที่แสดงที่ด้านบนของชีตการตรวจสอบสิทธิ์ ให้สร้างLocalizable.stringsที่มีเนื้อหาต่อไปนี้"Sign in with Firebase" = "Sign in to use ExampleApp";
ข้อมูลที่รวมอยู่ในมุมมองที่สร้างไว้ล่วงหน้า
เมื่อใช้ AuthPickerView คุณจะได้รับสิ่งต่อไปนี้
- งานนำเสนอชีต: UI การตรวจสอบสิทธิ์จะปรากฏเป็นชีตแบบโมดัล
- การนำทางในตัว: การนำทางอัตโนมัติระหว่างหน้าจอลงชื่อเข้าใช้ การกู้คืนรหัสผ่าน MFA ลิงก์อีเมล และการยืนยันทางโทรศัพท์
- การจัดการสถานะการตรวจสอบสิทธิ์: สลับระหว่าง UI การตรวจสอบสิทธิ์กับเนื้อหาโดยอัตโนมัติตาม
authService.authenticationState - ควบคุมผ่าน
isPresented: ควบคุมเวลาที่ชีตการให้สิทธิ์จะปรากฏโดยการตั้งค่าauthService.isPresented = true/false
ลักษณะการทำงานที่กำหนดเอง
AuthPickerViewเริ่มต้นจะกำหนดวิธีจัดการกับสถานการณ์ที่ซับซ้อนหลายอย่าง
ดังนี้
1. การแก้ไขความขัดแย้งของบัญชี
เมื่อเกิดข้อขัดแย้งของบัญชี (เช่น การลงชื่อเข้าใช้ด้วยข้อมูลเข้าสู่ระบบที่ลิงก์กับบัญชีอื่นอยู่แล้ว) AuthPickerView จะจัดการโดยอัตโนมัติ ดังนี้
- การอัปเกรดแบบไม่ระบุตัวตนที่ขัดแย้งกัน: หากเปิดใช้
shouldAutoUpgradeAnonymousUsersและเกิดความขัดแย้งระหว่างการอัปเกรดแบบไม่ระบุตัวตน ระบบจะออกจากระบบผู้ใช้ที่ไม่ระบุตัวตนโดยอัตโนมัติและลงชื่อเข้าใช้ด้วยข้อมูลเข้าสู่ระบบใหม่ - ความขัดแย้งอื่นๆ: สำหรับความขัดแย้งของข้อมูลเข้าสู่ระบบระหว่างบัญชีที่ไม่ใช่บัญชีที่ไม่ระบุตัวตน ระบบจะจัดเก็บข้อมูลเข้าสู่ระบบที่รอดำเนินการและพยายามลิงก์หลังจากลงชื่อเข้าใช้สำเร็จ
ซึ่งจัดการโดย AccountConflictModifier ที่ใช้ที่ระดับ NavigationStack
2. การตรวจสอบสิทธิ์แบบหลายปัจจัย (MFA)
เมื่อเปิดใช้ MFA ในการกำหนดค่า
- ตรวจหาโดยอัตโนมัติเมื่อต้องใช้ MFA ระหว่างการลงชื่อเข้าใช้
- แสดงหน้าจอการแก้ปัญหา MFA ที่เหมาะสม (SMS หรือ TOTP)
- จัดการขั้นตอนการลงทะเบียนและการจัดการ MFA
- รองรับทั้งปัจจัยรหัสผ่านแบบใช้ครั้งเดียว (OTP) ที่อิงตาม SMS และตามเวลา (TOTP)
3. การจัดการข้อผิดพลาด
มุมมองเริ่มต้นมีการจัดการข้อผิดพลาดในตัวดังนี้
- แสดงข้อความแสดงข้อผิดพลาดที่ใช้งานง่ายในกล่องโต้ตอบการแจ้งเตือน
- กรองข้อผิดพลาดที่จัดการภายในโดยอัตโนมัติ (เช่น ข้อผิดพลาดในการยกเลิก ความขัดแย้งที่จัดการโดยอัตโนมัติ)
- ใช้ข้อความแสดงข้อผิดพลาดที่แปลแล้วผ่าน
StringUtils - ข้อผิดพลาดจะเผยแพร่ผ่านคีย์สภาพแวดล้อม
reportError
4. การลงชื่อเข้าใช้ด้วยลิงก์ในอีเมล
เมื่อกำหนดค่าการลงชื่อเข้าใช้ด้วยลิงก์อีเมลแล้ว
- จัดเก็บอีเมลในพื้นที่เก็บข้อมูลของแอปโดยอัตโนมัติ
- จัดการการนำทาง Deep Link จากอีเมล
- จัดการขั้นตอนการยืนยันอีเมลทั้งหมด
- รองรับการอัปเกรดผู้ใช้ที่ไม่ระบุตัวตนผ่านลิงก์ในอีเมล
5. การอัปเกรดอัตโนมัติสำหรับผู้ใช้ที่ไม่ระบุชื่อ
เมื่อเปิดใช้ shouldAutoUpgradeAnonymousUsers
- พยายามลิงก์บัญชีที่ไม่ระบุตัวตนกับข้อมูลเข้าสู่ระบบใหม่โดยอัตโนมัติ
- เก็บรักษาข้อมูลผู้ใช้โดยการอัปเกรดแทนการแทนที่เซสชันที่ไม่ระบุตัวตน
- จัดการข้อขัดแย้งในการอัปเกรดแฮนเดิลอย่างราบรื่น
6. การตรวจสอบสิทธิ์อีกครั้งในมุมมองเริ่มต้น
การดำเนินการที่มีความละเอียดอ่อน เช่น การลบบัญชี การอัปเดตรหัสผ่าน หรือการยกเลิกการลงทะเบียนปัจจัย MFA จะต้องมีการตรวจสอบสิทธิ์ล่าสุด เมื่อใช้มุมมองเริ่มต้น ระบบจะจัดการการตรวจสอบสิทธิ์อีกครั้งโดยอัตโนมัติตามผู้ให้บริการลงชื่อเข้าใช้ของผู้ใช้
เมื่อการดำเนินการที่มีความละเอียดอ่อนต้องมีการตรวจสอบสิทธิ์อีกครั้ง มุมมองเริ่มต้นจะดำเนินการต่อไปนี้โดยอัตโนมัติ
ผู้ให้บริการ OAuth (Google, Apple, Facebook, Twitter ฯลฯ): แสดงการแจ้งเตือนที่ขอให้ผู้ใช้ยืนยัน จากนั้นรับข้อมูลเข้าสู่ระบบใหม่โดยอัตโนมัติและดำเนินการให้เสร็จสมบูรณ์
อีเมล/รหัสผ่าน: แสดงชีตที่แจ้งให้ผู้ใช้ป้อนรหัสผ่านก่อนดำเนินการต่อ
ลิงก์อีเมล: แสดงการแจ้งเตือนที่ขอให้ส่งอีเมลยืนยัน จากนั้นแสดงชีตพร้อมวิธีการตรวจสอบอีเมล ผู้ใช้แตะลิงก์ในอีเมลเพื่อทำการตรวจสอบสิทธิ์อีกครั้งให้เสร็จสมบูรณ์
โทรศัพท์: แสดงการแจ้งเตือนที่อธิบายว่าต้องมีการยืนยัน จากนั้นแสดงชีตสำหรับการยืนยันรหัส SMS
การดำเนินการจะลองอีกครั้งโดยอัตโนมัติหลังจากตรวจสอบสิทธิ์อีกครั้งสำเร็จ ไม่จำเป็นต้องใช้โค้ดเพิ่มเติมเมื่อใช้ 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 - การตรวจสอบสิทธิ์อีกครั้ง: จัดการข้อผิดพลาดในการตรวจสอบสิทธิ์อีกครั้งสำหรับการดำเนินการที่มีความละเอียดอ่อน (ดูการตรวจสอบสิทธิ์อีกครั้งในมุมมองที่กำหนดเองด้านล่าง)
การตรวจสอบสิทธิ์อีกครั้งในมุมมองที่กำหนดเอง
เมื่อสร้างมุมมองที่กำหนดเอง ให้จัดการการตรวจสอบสิทธิ์อีกครั้งโดยการตรวจหาข้อผิดพลาดที่เฉพาะเจาะจงและใช้โฟลว์ของคุณเอง การดำเนินการที่ละเอียดอ่อนจะทำให้เกิดข้อผิดพลาดในการตรวจสอบสิทธิ์อีกครั้ง 4 ประเภท ซึ่งแต่ละประเภทจะมีข้อมูลบริบท
รูปแบบการติดตั้งใช้งาน
ผู้ให้บริการ 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
}
}
ลิงก์อีเมล:
ตรวจหาข้อผิดพลาด ส่งอีเมลยืนยัน และจัดการ URL ขาเข้า
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 ที่กำหนดเองสำหรับบริการอื่นๆ นอกเหนือจากบริการที่มีอยู่ได้โดยทำดังนี้
⚠️ สำคัญ: คุณต้องกำหนดค่าผู้ให้บริการ OIDC (OpenID Connect) ในการตั้งค่าการตรวจสอบสิทธิ์ของโปรเจ็กต์ Firebase ก่อนจึงจะใช้งานได้ ในคอนโซล Firebase ให้ไปที่การตรวจสอบสิทธิ์ → วิธีการลงชื่อเข้าใช้ แล้วเพิ่มผู้ให้บริการ OIDC พร้อมข้อมูลเข้าสู่ระบบที่จำเป็น (รหัสไคลเอ็นต์, ข้อมูลลับไคลเอ็นต์, URL ผู้ออก) นอกจากนี้ คุณต้องลงทะเบียน URI การเปลี่ยนเส้นทาง OAuth ที่ Firebase ระบุไว้ในคอนโซลนักพัฒนาแอปของผู้ให้บริการด้วย ดูวิธีการตั้งค่าแบบละเอียดได้ที่เอกสารประกอบ OIDC ของ Firebase
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)
}
}