หากคุณอัปเกรดเป็น Firebase Authentication ด้วย Identity Platform คุณจะเพิ่ม SMS multi-factor authentication ลงในแอป iOS ได้
การรับรองความถูกต้องด้วยหลายปัจจัยช่วยเพิ่มความปลอดภัยของแอปของคุณ แม้ว่าผู้โจมตีมักจะเจาะรหัสผ่านและบัญชีโซเชียล แต่การสกัดกั้นข้อความนั้นยากกว่า
ก่อนที่คุณจะเริ่มต้น
เปิดใช้งานผู้ให้บริการอย่างน้อยหนึ่งรายที่รองรับการรับรองความถูกต้องด้วยหลายปัจจัย ผู้ให้บริการทุกรายรองรับ MFA ยกเว้น การตรวจสอบสิทธิ์ทางโทรศัพท์ การตรวจสอบสิทธิ์แบบไม่ระบุตัวตน และ Apple Game Center
ตรวจสอบให้แน่ใจว่าแอปของคุณยืนยันอีเมลของผู้ใช้ MFA ต้องการการยืนยันอีเมล วิธีนี้จะป้องกันไม่ให้ผู้ไม่หวังดีลงทะเบียนใช้บริการด้วยอีเมลที่พวกเขาไม่ได้เป็นเจ้าของ จากนั้นจึงล็อกเอาต์เจ้าของที่แท้จริงโดยเพิ่มปัจจัยที่สอง
เปิดใช้งานการยืนยันตัวตนแบบหลายปัจจัย
เปิดหน้าการ ตรวจสอบสิทธิ์ > วิธีลงชื่อเข้าใช้ ของคอนโซล Firebase
ในส่วน ขั้นสูง เปิดใช้งานการยืนยันตัวตนด้วย หลายปัจจัยทาง SMS
คุณควรป้อนหมายเลขโทรศัพท์ที่คุณจะทดสอบแอปด้วย แม้ว่าจะเป็นทางเลือก แต่ขอแนะนำให้ลงทะเบียนหมายเลขโทรศัพท์ทดสอบเพื่อหลีกเลี่ยงการควบคุมปริมาณระหว่างการพัฒนา
หากคุณยังไม่ได้อนุญาตโดเมนของแอป ให้เพิ่มลงในรายการอนุญาตในหน้าการ ตรวจสอบสิทธิ์ > การตั้งค่า ของคอนโซล Firebase
กำลังตรวจสอบแอปของคุณ
Firebase ต้องยืนยันว่าคำขอ SMS มาจากแอปของคุณ คุณสามารถทำได้สองวิธี:
การ แจ้งเตือน APN แบบเงียบ : เมื่อคุณลงชื่อเข้าใช้ผู้ใช้เป็นครั้งแรก Firebase สามารถส่งการแจ้งเตือนแบบเงียบไปยังอุปกรณ์ของผู้ใช้ การรับรองความถูกต้องสามารถดำเนินการต่อได้หากแอปได้รับการแจ้งเตือน โปรดทราบว่า ตั้งแต่ iOS 8.0 ขึ้นไป คุณไม่จำเป็นต้องขอให้ผู้ใช้อนุญาตการแจ้งเตือนแบบพุชเพื่อใช้วิธีนี้
การ ยืนยัน reCAPTCHA : หากคุณไม่สามารถส่งการแจ้งเตือนแบบเงียบได้ (เช่น เนื่องจากผู้ใช้ปิดใช้งานการรีเฟรชพื้นหลัง หรือคุณกำลังทดสอบแอปของคุณในโปรแกรมจำลอง iOS) คุณสามารถใช้ reCAPTCHA ได้ ในหลายกรณี reCAPTCHA จะแก้ปัญหาเองโดยอัตโนมัติโดยที่ผู้ใช้ไม่ต้องดำเนินการใดๆ
ใช้การแจ้งเตือนแบบเงียบ
วิธีเปิดใช้งานการแจ้งเตือน APN สำหรับใช้กับ Firebase:
ใน Xcode เปิดใช้งานการแจ้งเตือนแบบพุช สำหรับโครงการของคุณ
อัปโหลดคีย์การตรวจสอบสิทธิ์ APN ของคุณโดยใช้ Firebase Console (การเปลี่ยนแปลงของคุณจะส่งไปยัง Google Cloud Firebase โดยอัตโนมัติ) หากคุณยังไม่มีคีย์การตรวจสอบสิทธิ์ APN โปรดดูที่การ กำหนดค่า APN ด้วย FCM เพื่อเรียนรู้วิธีการขอรับ
เปิด คอนโซล Firebase
ไปที่ การตั้งค่าโครงการ
เลือกแท็บ Cloud Messaging
ภายใต้ คีย์การตรวจสอบสิทธิ์ APN ในส่วน การกำหนดค่าแอป iOS ให้คลิก อัปโหลด
เลือกคีย์ของคุณ
เพิ่ม ID คีย์สำหรับคีย์ คุณสามารถค้นหา ID คีย์ได้ที่ใต้ Certificates, Identifiers & Profiles ใน Apple Developer Member Center
คลิก อัปโหลด
หากคุณมีใบรับรอง APN อยู่แล้ว คุณสามารถอัปโหลดใบรับรองแทนได้
ใช้การยืนยัน reCAPTCHA
วิธีเปิดใช้งาน SDK ไคลเอ็นต์เพื่อใช้ reCAPTCHA:
เปิดการกำหนดค่าโครงการของคุณใน Xcode
คลิกสองครั้งที่ชื่อโปรเจ็กต์ในมุมมองทรีด้านซ้าย
เลือกแอปของคุณจากส่วน เป้าหมาย
เลือกแท็บ ข้อมูล
ขยายส่วน ประเภท URL
คลิกปุ่ม +
ป้อน ID ไคลเอ็นต์ที่ย้อนกลับของคุณในช่อง URL Schemes คุณจะพบค่านี้ในไฟล์กำหนดค่า
GoogleService-Info.plist
เป็นREVERSED_CLIENT_ID
เมื่อเสร็จแล้ว การกำหนดค่าของคุณควรมีลักษณะดังนี้:
คุณสามารถปรับแต่งวิธีที่แอปของคุณนำเสนอ SFSafariViewController
หรือ UIWebView
เมื่อแสดง reCAPTCHA ในการดำเนินการนี้ ให้สร้างคลาสแบบกำหนดเองที่สอดคล้องกับโปรโตคอล FIRAuthUIDelegate
และส่งต่อไปยัง verifyPhoneNumber:UIDelegate:completion:
การเลือกรูปแบบการลงทะเบียน
คุณสามารถเลือกได้ว่าแอปของคุณต้องการการยืนยันตัวตนแบบหลายปัจจัยหรือไม่ และจะลงทะเบียนผู้ใช้อย่างไรและเมื่อใด รูปแบบทั่วไปบางอย่าง ได้แก่ :
ลงทะเบียนปัจจัยที่สองของผู้ใช้เป็นส่วนหนึ่งของการลงทะเบียน ใช้วิธีนี้หากแอปของคุณต้องการการรับรองความถูกต้องด้วยหลายปัจจัยสำหรับผู้ใช้ทั้งหมด โปรดทราบว่าบัญชีต้องมีที่อยู่อีเมลที่ได้รับการยืนยันเพื่อลงทะเบียนปัจจัยที่สอง ดังนั้นขั้นตอนการลงทะเบียนของคุณจะต้องรองรับสิ่งนี้
เสนอตัวเลือกที่ข้ามได้เพื่อลงทะเบียนปัจจัยที่สองระหว่างการลงทะเบียน แอปที่ต้องการส่งเสริมแต่ไม่ต้องการการรับรองความถูกต้องด้วยหลายปัจจัยอาจชอบวิธีนี้
ให้ความสามารถในการเพิ่มปัจจัยที่สองจากบัญชีผู้ใช้หรือหน้าการจัดการโปรไฟล์ แทนที่จะเป็นหน้าจอลงชื่อสมัครใช้ สิ่งนี้ช่วยลดความขัดแย้งระหว่างขั้นตอนการลงทะเบียน ในขณะที่ยังคงทำให้การรับรองความถูกต้องด้วยหลายปัจจัยพร้อมใช้งานสำหรับผู้ใช้ที่มีความสำคัญต่อความปลอดภัย
ต้องเพิ่มปัจจัยที่สองทีละน้อยเมื่อผู้ใช้ต้องการเข้าถึงคุณสมบัติที่มีข้อกำหนดด้านความปลอดภัยเพิ่มขึ้น
การลงทะเบียนปัจจัยที่สอง
ในการลงทะเบียนปัจจัยรองใหม่สำหรับผู้ใช้:
ตรวจสอบผู้ใช้อีกครั้ง
ขอให้ผู้ใช้ป้อนหมายเลขโทรศัพท์
รับเซสชันหลายปัจจัยสำหรับผู้ใช้:
สวิฟต์
authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in // ... }
วัตถุประสงค์-C
[authResult.user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session, NSError * _Nullable error) { // ... }];
ส่งข้อความยืนยันไปยังโทรศัพท์ของผู้ใช้ ตรวจสอบว่าหมายเลขโทรศัพท์อยู่ในรูปแบบ
+
นำหน้าและไม่มีเครื่องหมายวรรคตอนหรือช่องว่างอื่นๆ (เช่น+15105551234
)สวิฟต์
// Send SMS verification code. PhoneAuthProvider.provider().verifyPhoneNumber( phoneNumber, uiDelegate: nil, multiFactorSession: session) { (verificationId, error) in // verificationId will be needed for enrollment completion. }
วัตถุประสงค์-C
// Send SMS verification code. [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber UIDelegate:nil multiFactorSession:session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { // verificationId will be needed for enrollment completion. }];
แม้ว่าจะไม่บังคับ แต่ควรแจ้งผู้ใช้ล่วงหน้าว่าพวกเขาจะได้รับข้อความ SMS และเป็นไปตามอัตรามาตรฐาน
วิธีการ
verifyPhoneNumber()
เริ่มกระบวนการตรวจสอบแอปในพื้นหลังโดยใช้การแจ้งเตือนแบบเงียบ หากไม่มีการแจ้งเตือนแบบเงียบ ระบบจะออกคำขอ reCAPTCHA แทนเมื่อส่งรหัส SMS แล้ว ขอให้ผู้ใช้ยืนยันรหัส จากนั้นใช้คำตอบเพื่อสร้าง
PhoneAuthCredential
:สวิฟต์
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId, verificationCode: verificationCode)
วัตถุประสงค์-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:kPhoneSecondFactorVerificationCode];
เริ่มต้นวัตถุยืนยัน:
สวิฟต์
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
วัตถุประสงค์-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
กรอกใบสมัคร คุณสามารถระบุชื่อที่ใช้แสดงสำหรับปัจจัยที่สอง สิ่งนี้มีประโยชน์สำหรับผู้ใช้ที่มีปัจจัยวินาทีหลายตัว เนื่องจากหมายเลขโทรศัพท์ถูกปกปิดระหว่างขั้นตอนการตรวจสอบสิทธิ์ (เช่น +1******1234)
สวิฟต์
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in // ... }
วัตถุประสงค์-C
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. [authResult.user.multiFactor enrollWithAssertion:assertion displayName:nil completion:^(NSError * _Nullable error) { // ... }];
รหัสด้านล่างแสดงตัวอย่างที่สมบูรณ์ของการลงทะเบียนปัจจัยที่สอง:
สวิฟต์
let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
// Send SMS verification code.
PhoneAuthProvider.provider().verifyPhoneNumber(
phoneNumber,
uiDelegate: nil,
multiFactorSession: session
) { (verificationId, error) in
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: phoneSecondFactorVerificationCode)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
// ...
}
}
})
วัตถุประสงค์-C
FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
NSError * _Nullable error) {
// Send SMS verification code.
[FIRPhoneAuthProvider.provider
verifyPhoneNumber:phoneNumber
UIDelegate:nil
multiFactorSession:session
completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
[user.multiFactor enrollWithAssertion:assertion
displayName:displayName
completion:^(NSError * _Nullable error) {
// ...
}];
}];
}];
ยินดีด้วย! คุณลงทะเบียนปัจจัยการรับรองความถูกต้องที่สองสำหรับผู้ใช้สำเร็จแล้ว
การลงชื่อเข้าใช้ผู้ใช้ด้วยปัจจัยที่สอง
ในการลงชื่อเข้าใช้ผู้ใช้ด้วยการยืนยันทาง SMS แบบสองปัจจัย:
ลงชื่อเข้าใช้ผู้ใช้ด้วยปัจจัยแรก จากนั้นพบข้อผิดพลาดที่ระบุว่าจำเป็นต้องมีการรับรองความถูกต้องด้วยหลายปัจจัย ข้อผิดพลาดนี้ประกอบด้วยตัวแก้ไข คำใบ้เกี่ยวกับปัจจัยที่สองที่ลงทะเบียน และเซสชันพื้นฐานที่พิสูจน์ว่าผู้ใช้ได้รับการรับรองความถูกต้องด้วยปัจจัยแรกสำเร็จ
ตัวอย่างเช่น หากปัจจัยแรกของผู้ใช้คืออีเมลและรหัสผ่าน:
สวิฟต์
Auth.auth().signIn( withEmail: email, password: password ) { (result, error) in let authError = error as NSError if authError?.code == AuthErrorCode.secondFactorRequired.rawValue { // The user is a multi-factor user. Second factor challenge is required. let resolver = authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver // ... } else { // Handle other errors such as wrong password. } }
วัตถุประสงค์-C
[FIRAuth.auth signInWithEmail:email password:password completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) { // User is not enrolled with a second factor and is successfully signed in. // ... } else { // The user is a multi-factor user. Second factor challenge is required. } }];
หากปัจจัยแรกของผู้ใช้คือผู้ให้บริการแบบรวมศูนย์ เช่น OAuth ให้ตรวจจับข้อผิดพลาดหลังจากเรียก
getCredentialWith()
หากผู้ใช้มีปัจจัยรองหลายตัวที่ลงทะเบียนไว้ ให้ถามพวกเขาว่าจะใช้ตัวใด คุณสามารถรับหมายเลขโทรศัพท์ที่ปิดบังด้วย
resolver.hints[selectedIndex].phoneNumber
และชื่อที่แสดงด้วยresolver.hints[selectedIndex].displayName
สวิฟต์
// Ask user which second factor to use. Then: if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID { // User selected a phone second factor. // ... } else { // Unsupported second factor. // Note that only phone second factors are currently supported. }
วัตถุประสงค์-C
FIRMultiFactorResolver *resolver = (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; // Ask user which second factor to use. Then: FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex]; if (hint.factorID == FIRPhoneMultiFactorID) { // User selected a phone second factor. // ... } else { // Unsupported second factor. // Note that only phone second factors are currently supported. }
ส่งข้อความยืนยันไปยังโทรศัพท์ของผู้ใช้:
สวิฟต์
// Send SMS verification code. let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo PhoneAuthProvider.provider().verifyPhoneNumber( with: hint, uiDelegate: nil, multiFactorSession: resolver.session ) { (verificationId, error) in // verificationId will be needed for sign-in completion. }
วัตถุประสงค์-C
// Send SMS verification code [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:hint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error != nil) { // Failed to verify phone number. } }];
เมื่อส่งรหัส SMS แล้ว ขอให้ผู้ใช้ยืนยันรหัสและใช้เพื่อสร้าง
PhoneAuthCredential
:สวิฟต์
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId!, verificationCode: verificationCodeFromUser)
วัตถุประสงค์-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:verificationCodeFromUser];
เริ่มต้นวัตถุยืนยันด้วยข้อมูลประจำตัว:
สวิฟต์
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
วัตถุประสงค์-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
แก้ไขการลงชื่อเข้าใช้ จากนั้นคุณสามารถเข้าถึงผลลัพธ์การลงชื่อเข้าใช้ดั้งเดิม ซึ่งรวมถึงข้อมูลเฉพาะของผู้ให้บริการมาตรฐานและข้อมูลรับรองการตรวจสอบสิทธิ์:
สวิฟต์
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(with: assertion) { (authResult, error) in // authResult will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // authResult.additionalUserInfo will contain data related to Google provider that // the user signed in with. // user.credential contains the Google OAuth credential. // user.credential.accessToken contains the Google OAuth access token. // user.credential.idToken contains the Google OAuth ID token. }
วัตถุประสงค์-C
// Complete sign-in. [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // User successfully signed in with the second factor phone number. } }];
รหัสด้านล่างแสดงตัวอย่างที่สมบูรณ์ของการลงชื่อเข้าใช้ผู้ใช้แบบหลายปัจจัย:
สวิฟต์
Auth.auth().signIn(
withEmail: email,
password: password
) { (result, error) in
let authError = error as NSError?
if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
let resolver =
authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
// Ask user which second factor to use.
// ...
// Then:
let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
// Send SMS verification code
PhoneAuthProvider.provider().verifyPhoneNumber(
with: hint,
uiDelegate: nil,
multiFactorSession: resolver.session
) { (verificationId, error) in
if error != nil {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: verificationCodeFromUser)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete sign-in.
resolver.resolveSignIn(with: assertion) { (authResult, error) in
if error != nil {
// User successfully signed in with the second factor phone number.
}
}
}
}
}
วัตถุประสงค์-C
[FIRAuth.auth signInWithEmail:email
password:password
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
// User is not enrolled with a second factor and is successfully signed in.
// ...
} else {
FIRMultiFactorResolver *resolver =
(FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
// Ask user which second factor to use.
// ...
// Then:
FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
// Send SMS verification code
[FIRPhoneAuthProvider.provider
verifyPhoneNumberWithMultiFactorInfo:hint
UIDelegate:nil
multiFactorSession:resolver.session
completion:^(NSString * _Nullable verificationID,
NSError * _Nullable error) {
if (error != nil) {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider
credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete sign-in.
[resolver resolveSignInWithAssertion:assertion
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error != nil) {
// User successfully signed in with the second factor phone number.
}
}];
}];
}
}];
ยินดีด้วย! คุณลงชื่อเข้าใช้ผู้ใช้โดยใช้การรับรองความถูกต้องด้วยหลายปัจจัยสำเร็จแล้ว
อะไรต่อไป
- จัดการผู้ใช้หลายปัจจัย ทางโปรแกรมด้วย Admin SDK