คุณสามารถอนุญาตให้ผู้ใช้ตรวจสอบสิทธิ์กับ Firebase โดยใช้ผู้ให้บริการ OAuth เช่น GitHub โดยการผสานรวมการเข้าสู่ระบบ OAuth ทั่วไปไว้ในแอปโดยใช้ Firebase SDK เพื่อดำเนินการตามขั้นตอนการลงชื่อเข้าใช้ตั้งแต่ต้นจนจบ
ก่อนเริ่มต้น
หากต้องการลงชื่อเข้าใช้ผู้ใช้โดยใช้บัญชี GitHub คุณต้องเปิดใช้ GitHub เป็นผู้ให้บริการลงชื่อเข้าใช้สำหรับโปรเจ็กต์ Firebase ก่อน โดยทำดังนี้
ใช้ Swift Package Manager เพื่อติดตั้งและจัดการทรัพยากร Dependency ของ Firebase
- เปิดโปรเจ็กต์แอปใน Xcode แล้วไปที่ไฟล์ > เพิ่มแพ็กเกจ
- เมื่อได้รับข้อความแจ้ง ให้เพิ่มที่เก็บ Firebase SDK สำหรับแพลตฟอร์ม Apple ดังนี้
- เลือกคลัง Firebase Authentication
- เพิ่ม Flag
-ObjC
ลงในส่วน Other Linker Flags ของการตั้งค่าบิลด์เป้าหมาย - เมื่อเสร็จแล้ว Xcode จะเริ่มจับคู่ข้อมูลและดาวน์โหลดทรัพยากร Dependency ในเบื้องหลังโดยอัตโนมัติ
https://github.com/firebase/firebase-ios-sdk.git
ตอนนี้ให้ทำตามขั้นตอนการกําหนดค่าต่อไปนี้
- เปิดส่วน Auth ในคอนโซล Firebase
- ในแท็บวิธีการลงชื่อเข้าใช้ ให้เปิดใช้ผู้ให้บริการ GitHub
- เพิ่มรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์จากคอนโซลของนักพัฒนาซอฟต์แวร์ของผู้ให้บริการนั้นลงในการกำหนดค่าผู้ให้บริการ ดังนี้
- ลงทะเบียนแอปเป็นแอปพลิเคชันของนักพัฒนาแอปใน GitHub และรับรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์ของ OAuth 2.0
- ตรวจสอบว่าได้ตั้งค่า URI การเปลี่ยนเส้นทาง OAuth ของ Firebase (เช่น
my-app-12345.firebaseapp.com/__/auth/handler
) เป็น URL เรียกกลับการให้สิทธิ์ในหน้าการตั้งค่าของแอปในการกำหนดค่าแอป GitHub
- คลิกบันทึก
จัดการขั้นตอนการลงชื่อเข้าใช้ด้วย Firebase SDK
หากต้องการจัดการขั้นตอนการลงชื่อเข้าใช้ด้วย Firebase SDK สําหรับแพลตฟอร์ม Apple ให้ทําตามขั้นตอนต่อไปนี้
เพิ่มรูปแบบ URL ที่กําหนดเองลงในโปรเจ็กต์ Xcode โดยทำดังนี้
- เปิดการกําหนดค่าโปรเจ็กต์: ดับเบิลคลิกชื่อโปรเจ็กต์ในมุมมองแบบต้นไม้ทางด้านซ้าย เลือกแอปจากส่วนเป้าหมาย จากนั้นเลือกแท็บข้อมูล แล้วขยายส่วนประเภท URL
- คลิกปุ่ม + แล้วเพิ่มรหัสแอปที่เข้ารหัสเป็นสคีมา URL คุณดูรหัสแอปที่เข้ารหัสได้ในหน้าการตั้งค่าทั่วไปของคอนโซล Firebase ในส่วนสำหรับแอป iOS ของคุณ เว้นว่างช่องอื่นๆ ไว้
เมื่อเสร็จแล้ว ไฟล์ config ควรมีลักษณะคล้ายกับตัวอย่างต่อไปนี้ (แต่ใช้ค่าเฉพาะแอปพลิเคชันของคุณ)
สร้างอินสแตนซ์ของ OAuthProvider โดยใช้รหัสผู้ให้บริการ github.com
var provider = OAuthProvider(providerID: "github.com")
FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"github.com"];
ไม่บังคับ: ระบุพารามิเตอร์ OAuth ที่กําหนดเองเพิ่มเติมที่ต้องการส่งไปกับคําขอ OAuth
provider.customParameters = [ "allow_signup": "false" ]
[provider setCustomParameters:@{@"allow_signup": @"false"}];
ดูพารามิเตอร์ที่ GitHub รองรับได้ที่เอกสารประกอบเกี่ยวกับ OAuth ของ GitHub โปรดทราบว่าคุณไม่สามารถส่งพารามิเตอร์ที่จําเป็นสําหรับ Firebase ด้วย
setCustomParameters
พารามิเตอร์เหล่านี้คือ client_id, redirect_uri, response_type, scope และ stateไม่บังคับ: ระบุขอบเขต OAuth 2.0 เพิ่มเติมนอกเหนือจากโปรไฟล์พื้นฐานที่คุณต้องการขอจากผู้ให้บริการตรวจสอบสิทธิ์ หากแอปพลิเคชันของคุณต้องใช้สิทธิ์เข้าถึงข้อมูลส่วนตัวของผู้ใช้จาก GitHub API คุณจะต้องขอสิทธิ์เข้าถึง GitHub API ในส่วนสิทธิ์ API ในคอนโซลนักพัฒนาซอฟต์แวร์ของ GitHub ขอบเขต OAuth ที่ขอต้องตรงกันทุกประการกับขอบเขตที่กำหนดค่าไว้ล่วงหน้าในสิทธิ์ API ของแอป
// Request read access to a user's email addresses. // This must be preconfigured in the app's API permissions. provider.scopes = ["user:email"]
// Request read access to a user's email addresses. // This must be preconfigured in the app's API permissions. [provider setScopes:@[@"user:email"]];
ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบเกี่ยวกับขอบเขตของ GitHub
ไม่บังคับ: หากต้องการปรับแต่งวิธีที่แอปแสดง
SFSafariViewController
หรือUIWebView
เมื่อแสดง reCAPTCHA ต่อผู้ใช้ ให้สร้างคลาสที่กำหนดเองซึ่งเป็นไปตามโปรโตคอลAuthUIDelegate
แล้วส่งไปยังcredentialWithUIDelegate
ตรวจสอบสิทธิ์กับ Firebase โดยใช้ออบเจ็กต์ผู้ให้บริการ OAuth
provider.getCredentialWith(nil) { credential, error in if error != nil { // Handle error. } if credential != nil { Auth().signIn(with: credential) { authResult, error in if error != nil { // Handle error. } // User is signed in. // IdP data available in authResult.additionalUserInfo.profile. guard let oauthCredential = authResult.credential as? OAuthCredential else { return } // GitHub OAuth access token can also be retrieved by: // oauthCredential.accessToken // GitHub OAuth ID token can be retrieved by calling: // oauthCredential.idToken } } }
[provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) { if (error) { // Handle error. } if (credential) { [[FIRAuth auth] signInWithCredential:credential completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { if (error) { // Handle error. } // User is signed in. // IdP data available in authResult.additionalUserInfo.profile. FIROAuthCredential *oauthCredential = (FIROAuthCredential *)authResult.credential; // GitHub OAuth access token can also be retrieved by: // oauthCredential.accessToken // GitHub OAuth ID token can be retrieved by calling: // oauthCredential.idToken }]; } }];
คุณเรียกใช้ GitHub API ได้โดยใช้โทเค็นการเข้าถึง OAuth
เช่น หากต้องการดูข้อมูลโปรไฟล์พื้นฐาน คุณสามารถเรียกใช้ REST API โดยส่งโทเค็นการเข้าถึงในส่วนหัว
Authorization
ดังนี้https://api.github.com/user
แม้ว่าตัวอย่างข้างต้นจะเน้นไปที่ขั้นตอนการลงชื่อเข้าใช้ แต่คุณก็ลิงก์ผู้ให้บริการ GitHub กับผู้ใช้ที่มีอยู่ได้เช่นกัน เช่น คุณสามารถลิงก์ผู้ให้บริการหลายรายกับผู้ใช้รายเดียวกันเพื่อให้ผู้ใช้ลงชื่อเข้าใช้ด้วยผู้ให้บริการใดก็ได้
Auth().currentUser.link(withCredential: credential) { authResult, error in if error != nil { // Handle error. } // GitHub credential is linked to the current user. // IdP data available in authResult.additionalUserInfo.profile. // GitHub OAuth access token can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // GitHub OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken }
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { // Handle error. } // GitHub credential is linked to the current user. // IdP data available in authResult.additionalUserInfo.profile. // GitHub OAuth access token is can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // GitHub OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }];
คุณใช้รูปแบบเดียวกันกับ
reauthenticateWithCredential
ได้ ซึ่งจะใช้เพื่อดึงข้อมูลเข้าสู่ระบบใหม่สำหรับการดำเนินการที่มีความละเอียดอ่อนซึ่งต้องมีการเข้าสู่ระบบครั้งล่าสุดAuth().currentUser.reauthenticateWithCredential(withCredential: credential) { authResult, error in if error != nil { // Handle error. } // User is re-authenticated with fresh tokens minted and // should be able to perform sensitive operations like account // deletion and email or password update. // IdP data available in result.additionalUserInfo.profile. // Additional OAuth access token is can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // GitHub OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken }
[[FIRAuth auth].currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { // Handle error. } // User is re-authenticated with fresh tokens minted and // should be able to perform sensitive operations like account // deletion and email or password update. // IdP data available in result.additionalUserInfo.profile. // Additional OAuth access token is can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // GitHub OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }];
การจัดการข้อผิดพลาด account-exists-with-different-credential
หากคุณเปิดใช้การตั้งค่าบัญชี 1 บัญชีต่ออีเมล 1 รายการในคอนโซล Firebase เมื่อผู้ใช้พยายามลงชื่อเข้าใช้ผู้ให้บริการ (เช่น GitHub) ด้วยอีเมลที่มีอยู่แล้วสำหรับผู้ให้บริการของผู้ใช้ Firebase รายอื่น (เช่น Google) ระบบจะแสดงข้อผิดพลาด FIRAuthErrorCodeAccountExistsWithDifferentCredential
พร้อมกับออบเจ็กต์ FIRAuthCredential
ชั่วคราว (ข้อมูลเข้าสู่ระบบ GitHub) หากต้องการลงชื่อเข้าใช้ผู้ให้บริการที่ต้องการให้เสร็จสมบูรณ์ ผู้ใช้ต้องลงชื่อเข้าใช้ผู้ให้บริการที่มีอยู่ (Google) ก่อน แล้วจึงลิงก์กับ FIRAuthCredential
เดิม (ข้อมูลเข้าสู่ระบบ GitHub) ซึ่งจะมีลักษณะดังภาพด้านล่าง
// Sign-in with an OAuth credential. provider.getCredentialWith(nil) { credential, error in // An account with the same email already exists. if (error as NSError?)?.code == AuthErrorCode.accountExistsWithDifferentCredential.rawValue { // Get pending credential and email of existing account. let existingAcctEmail = (error! as NSError).userInfo[AuthErrorUserInfoEmailKey] as! String let pendingCred = (error! as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as! AuthCredential // Lookup existing account identifier by the email. Auth.auth().fetchProviders(forEmail:existingAcctEmail) { providers, error in // Existing email/password account. if (providers?.contains(EmailAuthProviderID))! { // Existing password account for email. Ask user to provide the password of the // existing account. // Sign in with existing account. Auth.auth().signIn(withEmail:existingAcctEmail, password:password) { user, error in // Successfully signed in. if user != nil { // Link pending credential to account. Auth.auth().currentUser?.linkAndRetrieveData(with: pendingCred) { result, error in // ... } } } } } return } // Other errors. if error != nil { // handle the error. return } // Sign in with the credential. if credential != nil { Auth.auth().signInAndRetrieveData(with: credential!) { result, error in if error != nil { // handle the error. return } } } }
// Sign-in with an OAuth credential. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) { // An account with the same email already exists. if (error.code == FIRAuthErrorCodeAccountExistsWithDifferentCredential) { // Get pending credential and email of existing account. NSString *existingAcctEmail = error.userInfo[FIRAuthErrorUserInfoEmailKey]; FIRAuthCredential *pendingCred = error.userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey]; // Lookup existing account identifier by the email. [[FIRAuth auth] fetchProvidersForEmail:existingAcctEmail completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) { // Existing email/password account. if ( [providers containsObject:FIREmailAuthProviderID] ) { // Existing password account for email. Ask user to provide the password of the // existing account. // Sign in with existing account. [[FIRAuth auth] signInWithEmail:existingAcctEmail password:password completion:^(FIRUser *user, NSError *error) { // Successfully signed in. if (user) { // Link pending credential to account. [[FIRAuth auth].currentUser linkWithCredential:pendingCred completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }]; } }]; } }]; return; } // Other errors. if (error) { // handle the error. return; } // Sign in with the credential. if (credential) { [[FIRAuth auth] signInAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { if (error) { // handle the error. return; } }]; } }];
ขั้นตอนถัดไป
หลังจากผู้ใช้ลงชื่อเข้าใช้เป็นครั้งแรก ระบบจะสร้างบัญชีผู้ใช้ใหม่และลิงก์กับข้อมูลเข้าสู่ระบบ ซึ่งก็คือชื่อผู้ใช้และรหัสผ่าน หมายเลขโทรศัพท์ หรือข้อมูลผู้ให้บริการตรวจสอบสิทธิ์ที่ผู้ใช้ลงชื่อเข้าใช้ด้วย ระบบจะจัดเก็บบัญชีใหม่นี้เป็นส่วนหนึ่งของโปรเจ็กต์ Firebase และใช้เพื่อระบุผู้ใช้ในแอปทุกแอปในโปรเจ็กต์ได้ ไม่ว่าผู้ใช้จะลงชื่อเข้าใช้ด้วยวิธีใดก็ตาม
-
ในแอป คุณสามารถดูข้อมูลโปรไฟล์พื้นฐานของผู้ใช้ได้จากออบเจ็กต์
User
โปรดดูหัวข้อจัดการผู้ใช้ ใน Firebase Realtime Database และ Cloud Storage กฎความปลอดภัย คุณสามารถรับรหัสผู้ใช้ที่ไม่ซ้ำของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปร
auth
และนำไปใช้ควบคุมข้อมูลที่ผู้ใช้เข้าถึงได้
คุณสามารถอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอปโดยใช้ผู้ให้บริการตรวจสอบสิทธิ์หลายรายได้โดยการลิงก์ข้อมูลเข้าสู่ระบบของผู้ให้บริการตรวจสอบสิทธิ์กับบัญชีผู้ใช้ที่มีอยู่
หากต้องการออกจากระบบของผู้ใช้ ให้โทร
signOut:
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
นอกจากนี้ คุณอาจต้องเพิ่มโค้ดการจัดการข้อผิดพลาดสำหรับข้อผิดพลาดทั้งหมดของการตรวจสอบสิทธิ์ ดูจัดการข้อผิดพลาด