在 Apple 平台上使用 OpenID Connect 進行驗證

如果您已升級至使用 Identity Platform 進行 Firebase 驗證,則可以使用您選擇的 OpenID Connect (OIDC) 相容供應商透過 Firebase 對使用者進行驗證。這使得可以使用 Firebase 本身不支援的身份提供者。

在你開始之前

要使用 OIDC 提供者登入用戶,您必須先從提供者收集一些資訊:

  • 客戶端 ID :提供者唯一的字串,用於識別您的應用程式。您的提供者可能會為您支援的每個平台分配不同的客戶端 ID。這是您的提供者頒發的 ID 令牌中的aud聲明的值之一。

  • 客戶端金鑰:提供者用來確認客戶端 ID 所有權的秘密字串。對於每個客戶端 ID,您都需要一個相符的客戶端金鑰。 (僅當您使用auth code flow時才需要此值,強烈建議這樣做。)

  • Issuer :標識您的提供者的字串。該值必須是一個 URL,當附加/.well-known/openid-configuration時,它是提供者的 OIDC 發現文件的位置。例如,如果頒發者是https://auth.example.com ,則發現文件必須位於https://auth.example.com/.well-known/openid-configuration

獲得上述資訊後,啟用 OpenID Connect 作為您的 Firebase 專案的登入提供者:

  1. 將 Firebase 新增到您的 iOS 專案

  2. 如果您尚未升級到具有 Identity Platform 的 Firebase 驗證,請升級。 OpenID Connect 驗證僅在升級的專案中可用。

  3. 在 Firebase 控制台的登入提供者頁面上,按一下新增提供者,然後按一下OpenID Connect

  4. 選擇您將使用授權程式碼流程還是隱式授權流程

    如果您的提供者支持,您應該始終使用代碼流。隱式流的安全性較低,強烈建議不要使用它。

  5. 為該提供者指定一個名稱。請注意產生的提供者 ID:類似於oidc.example-provider 。當您向應用程式新增登入代碼時,您將需要此 ID。

  6. 指定您的客戶端 ID 和客戶端金鑰,以及提供者的頒發者字串。這些值必須與您的提供者指派給您的值完全相符。

  7. 儲存您的變更。

使用 Firebase SDK 處理登入流程

使用 OIDC 提供者對 Firebase 使用者進行身份驗證的最簡單方法是使用 Firebase SDK 處理整個登入流程。

若要使用 Firebase Apple 平台 SDK 處理登入流程,請依照下列步驟操作:

  1. 將自訂 URL 方案新增至您的 Xcode 專案:

    1. 開啟專案配置:雙擊左側樹視圖中的專案名稱。從“目標”部分選擇您的應用程序,然後選擇“資訊”選項卡,並展開“URL 類型”部分。
    2. 點擊+按鈕,並將您的編碼應用程式 ID 新增為 URL 方案。您可以在 Firebase 控制台的「常規設定」頁面上的 iOS 應用程式部分中找到您的編碼應用程式 ID。將其他欄位留空。

      完成後,您的配置應類似於以下內容(但具有特定於應用程式的值):

      Xcode的自訂URL方案設定介面截圖
  2. 使用您在 Firebase 控制台中取得的提供者 ID 建立OAuthProvider的實例。

    迅速

    var provider = OAuthProvider(providerID: "oidc.example-provider")
    

    Objective-C

    FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"oidc.example-provider"];
    
  3. 可選:指定要與 OAuth 請求一起傳送的其他自訂 OAuth 參數。

    迅速

    provider.customParameters = [
      "login_hint": "user@example.com"
    ]
    

    Objective-C

    [provider setCustomParameters:@{@"login_hint": @"user@example.com"}];
    

    請諮詢您的提供者以了解其支援的參數。請注意,您無法使用setCustomParameters傳遞 Firebase 所需的參數。這些參數是client_idresponse_typeredirect_uristatescoperesponse_mode

  4. 選用:指定您想要從身分驗證提供者要求的基本設定檔以外的其他 OAuth 2.0 範圍。

    迅速

    provider.scopes = ["mail.read", "calendars.read"]
    

    Objective-C

    [provider setScopes:@[@"mail.read", @"calendars.read"]];
    

    請諮詢您的提供者以了解其支援的範圍。

  5. 選用:如果要自訂應用程式在向使用者顯示 reCAPTCHA 時呈現SFSafariViewControllerUIWebView的方式,請建立一個符合AuthUIDelegate協定的自訂類別。

  6. 使用 OAuth 提供者物件透過 Firebase 進行身份驗證。

    迅速

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    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.
          // OAuth access token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.accessToken
          // OAuth ID token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.idToken
        }
      }
    }
    

    Objective-C

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    [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.
          // OAuth access token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).accessToken
          // OAuth ID token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).idToken
        }];
      }
    }];
    
  7. 雖然上述範例著重於登入流程,但您也可以使用linkWithCredential將 OIDC 提供者連結到現有使用者。例如,您可以將多個提供者連結到同一用戶,允許他們使用其中任一提供者登入。

    迅速

    Auth().currentUser.link(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    Objective-C

    [[FIRAuth auth].currentUser
        linkWithCredential:credential
                completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    
  8. 相同的模式可以與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 can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    Objective-C

    [[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 can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    

手動處理登入流程

如果您已在應用程式中實作 OpenID Connect 登入流程,則可以直接使用 ID 令牌透過 Firebase 進行驗證:

迅速

let credential = OAuthProvider.credential(
    withProviderID: "oidc.example-provider",  // As registered in Firebase console.
    idToken: idToken,  // ID token from OpenID Connect flow.
    rawNonce: nil
)
Auth.auth().signIn(with: credential) { authResult, error in
    if error {
        // Handle error.
        return
    }
    // User is signed in.
    // IdP data available in authResult?.additionalUserInfo?.profile
}

Objective-C

FIROAuthCredential *credential =
    [FIROAuthProvider credentialWithProviderID:@"oidc.example-provider"  // As registered in Firebase console.
                                       IDToken:idToken  // ID token from OpenID Connect flow.
                                      rawNonce:nil];
[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                      NSError * _Nullable error) {
    if (error != nil) {
        // Handle error.
        return;
    }
    // User is signed in.
    // IdP data available in authResult.additionalUserInfo.profile
}];

下一步

使用者首次登入後,系統會建立新的使用者帳戶,並將其連結到使用者登入時所使用的憑證(即使用者名稱和密碼、電話號碼或驗證提供者資訊)。此新帳戶將作為 Firebase 專案的一部分存儲,並且可用於識別專案中每個應用程式中的用戶,無論用戶如何登入。

  • 在您的應用程式中,您可以從User物件取得使用者的基本個人資料資訊。請參閱管理用戶

  • 在 Firebase 即時資料庫和雲端儲存安全性規則中,您可以從auth變數取得登入使用者的唯一使用者 ID,並使用它來控制使用者可以存取哪些資料。

您可以透過將身分驗證提供者憑證連結到現有使用者帳戶,允許使用者使用多個驗證提供者登入您的應用程式。

若要登出用戶,請呼叫signOut:

迅速

let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}

Objective-C

NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

您可能還需要為所有身份驗證錯誤新增錯誤處理代碼。請參閱處理錯誤