ตรวจสอบสิทธิ์โดยใช้ GitHub บนแพลตฟอร์ม Apple

คุณอนุญาตให้ผู้ใช้ตรวจสอบสิทธิ์กับ Firebase ได้โดยใช้ผู้ให้บริการ OAuth เช่น GitHub โดยการผสานรวมการเข้าสู่ระบบ OAuth ทั่วไปเข้ากับแอปโดยใช้ Firebase SDK เพื่อ ดำเนินการตามขั้นตอนการลงชื่อเข้าใช้ตั้งแต่ต้นทางถึงปลายทาง

ก่อนเริ่มต้น

หากต้องการลงชื่อเข้าใช้ให้ผู้ใช้ด้วยบัญชี GitHub คุณต้องเปิดใช้ GitHub สำหรับการลงชื่อเข้าใช้ก่อน ของผู้ให้บริการสำหรับโปรเจ็กต์ Firebase ของคุณ

ใช้ Swift Package Manager เพื่อติดตั้งและจัดการทรัพยากร Dependency ของ Firebase

  1. เปิดโปรเจ็กต์แอปใน Xcode แล้วไปที่ไฟล์ > เพิ่มแพ็กเกจ
  2. เมื่อได้รับข้อความแจ้ง ให้เพิ่มที่เก็บ SDK สำหรับแพลตฟอร์ม Firebase ของ Apple ดังนี้
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. เลือกไลบรารี Firebase Authentication
  5. เพิ่มแฟล็ก -ObjC ลงในส่วนแฟล็ก Linker อื่นๆ ของการตั้งค่าบิลด์ของเป้าหมาย
  6. เมื่อเสร็จแล้ว Xcode จะเริ่มแก้ปัญหาและดาวน์โหลด ทรัพยากร Dependency ในเบื้องหลัง

จากนั้นให้ทำตามขั้นตอนการกำหนดค่าต่อไปนี้

  1. ในคอนโซล Firebase ให้เปิดส่วน Auth
  2. ในแท็บวิธีการลงชื่อเข้าใช้ ให้เปิดใช้ผู้ให้บริการ GitHub
  3. เพิ่มรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์จาก Play Console ของผู้ให้บริการรายนั้นลงใน การกำหนดค่าผู้ให้บริการ:
    1. ลงทะเบียนแอป ในฐานะแอปพลิเคชันสำหรับนักพัฒนาซอฟต์แวร์ใน GitHub และรับรหัสไคลเอ็นต์ OAuth 2.0 ของแอป และรหัสลับไคลเอ็นต์
    2. ตรวจสอบว่า URL การเปลี่ยนเส้นทาง OAuth ของ Firebase (เช่น my-app-12345.firebaseapp.com/__/auth/handler) มีการตั้งค่าเป็น URL เรียกกลับเรื่องการให้สิทธิ์ในหน้าการตั้งค่าของแอปบนหน้า การกำหนดค่าของแอป GitHub
  4. คลิกบันทึก

จัดการขั้นตอนการลงชื่อเข้าใช้ด้วย Firebase SDK

หากต้องการจัดการขั้นตอนการลงชื่อเข้าใช้ด้วย SDK แพลตฟอร์ม Firebase ของ Apple ให้ทำตามขั้นตอนต่อไปนี้

  1. เพิ่มสคีม URL ที่กำหนดเองลงในโปรเจ็กต์ Xcode ของคุณดังนี้

    1. เปิดการกำหนดค่าโปรเจ็กต์: ดับเบิลคลิกชื่อโปรเจ็กต์ใน มุมมองต้นไม้ด้านซ้าย เลือกแอปจากส่วนเป้าหมาย จากนั้น เลือกแท็บข้อมูล และขยายส่วนประเภท URL
    2. คลิกปุ่ม + แล้วเพิ่มรหัสแอปที่เข้ารหัสเป็น URL สคีม คุณดูรหัสแอปที่เข้ารหัสได้ใน ข้อมูลทั่วไป การตั้งค่าของคอนโซล Firebase ในส่วนสำหรับ iOS แอป เว้นฟิลด์อื่นๆ ว่างไว้

      เมื่อดำเนินการเสร็จแล้ว ค่ากำหนดของคุณควรมีลักษณะคล้ายกับ ดังต่อไปนี้ (แต่เป็นค่าเฉพาะแอปพลิเคชัน)

      ภาพหน้าจอของอินเทอร์เฟซการตั้งค่ารูปแบบ URL ที่กําหนดเองของ Xcode

  2. สร้างอินสแตนซ์ของ OAuthProvider โดยใช้รหัสผู้ให้บริการ github.com

    SwiftObjective-C
        var provider = OAuthProvider(providerID: "github.com")
        
        FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"github.com"];
        
  3. ไม่บังคับ: ระบุพารามิเตอร์ OAuth ที่กำหนดเองเพิ่มเติมที่ต้องการ ส่งด้วยคำขอ OAuth

    SwiftObjective-C
        provider.customParameters = [
          "allow_signup": "false"
        ]
        
        [provider setCustomParameters:@{@"allow_signup": @"false"}];
        

    สำหรับพารามิเตอร์ที่ GitHub รองรับ โปรดดู เอกสารประกอบของ GitHub OAuth โปรดทราบว่าคุณไม่สามารถส่งพารามิเตอร์ที่จําเป็นของ Firebase ด้วย setCustomParameters พารามิเตอร์เหล่านี้คือ client_id redirect_uri, response_type, scope และ state

  4. ไม่บังคับ: ระบุขอบเขต OAuth 2.0 เพิ่มเติมที่นอกเหนือจากโปรไฟล์พื้นฐานที่ ที่ต้องการขอจากผู้ให้บริการตรวจสอบสิทธิ์ หากแอปพลิเคชันของคุณ ต้องมีสิทธิ์เข้าถึงข้อมูลผู้ใช้ส่วนตัวจาก GitHub API คุณจะต้อง ขอสิทธิ์ในการเข้าถึง GitHub API ภายใต้สิทธิ์ของ API ในส่วน GitHub Developer Console ขอบเขต OAuth ที่ขอต้องตรงกันทุกประการกับ รายการที่กำหนดค่าไว้ล่วงหน้าในสิทธิ์ API ของแอป

    SwiftObjective-C
        // 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

  5. ไม่บังคับ: หากต้องการปรับแต่งวิธีที่แอปนำเสนอ SFSafariViewControllerหรือUIWebView เมื่อ การแสดง reCAPTCHA แก่ผู้ใช้ ให้สร้างคลาสที่กำหนดเองที่สอดคล้องกับ ลงในโปรโตคอล AuthUIDelegate และส่งไปยัง credentialWithUIDelegate

  6. ตรวจสอบสิทธิ์กับ Firebase โดยใช้ออบเจ็กต์ผู้ให้บริการ OAuth

    SwiftObjective-C
        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
            }];
          }
        }];
        

    ด้วยการใช้โทเค็นเพื่อการเข้าถึง OAuth คุณสามารถเรียก GitHub API

    ตัวอย่างเช่น หากต้องการดูข้อมูลโปรไฟล์พื้นฐาน คุณสามารถเรียกใช้ REST API การส่งโทเค็นเพื่อการเข้าถึงในส่วนหัว Authorization:

    https://api.github.com/user
  7. แม้ว่าตัวอย่างข้างต้นจะเน้นที่ขั้นตอนการลงชื่อเข้าใช้ แต่คุณก็มี ความสามารถในการลิงก์ผู้ให้บริการ GitHub กับผู้ใช้ที่มีอยู่ ตัวอย่างเช่น คุณสามารถ ลิงก์ผู้ให้บริการหลายรายกับผู้ใช้รายเดียวกันเพื่อให้ผู้ให้บริการรายนั้นๆ ลงชื่อเข้าใช้ได้

    SwiftObjective-C
        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
        }];
        
  8. รูปแบบเดียวกันนี้สามารถใช้กับ reauthenticateWithCredential ซึ่งสามารถ ใช้เพื่อเรียกข้อมูลข้อมูลเข้าสู่ระบบใหม่สำหรับการดำเนินการที่มีความละเอียดอ่อนซึ่งจำเป็นต้องใช้ การเข้าสู่ระบบครั้งล่าสุด

    SwiftObjective-C
        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
        }];
        

หากคุณเปิดใช้การตั้งค่า 1 บัญชีต่ออีเมลในคอนโซล Firebase เมื่อผู้ใช้พยายามลงชื่อเข้าใช้ระบบของผู้ให้บริการ (เช่น GitHub) ด้วยอีเมลที่ อยู่กับผู้ให้บริการ Firebase รายอื่น (เช่น Google) โยน FIRAuthErrorCodeAccountExistsWithDifferentCredential พร้อมกับ ออบเจ็กต์ FIRAuthCredential รายการ (ข้อมูลเข้าสู่ระบบของ GitHub) วิธีลงชื่อเข้าใช้ ผู้ให้บริการที่ต้องการนั้น ผู้ใช้ต้องลงชื่อเข้าใช้กับผู้ให้บริการที่มีอยู่ (Google) ก่อน จากนั้นจึงลิงก์กับ FIRAuthCredential เดิม (ข้อมูลเข้าสู่ระบบของ GitHub) ดังที่แสดงด้านล่าง

SwiftObjective-C
  // 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:

SwiftObjective-C
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;
}

คุณอาจต้องเพิ่มโค้ดการจัดการข้อผิดพลาดสำหรับการตรวจสอบสิทธิ์ทั้งหมดด้วย โปรดดูหัวข้อจัดการข้อผิดพลาด