Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

在 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. 打開您的項目配置:雙擊左側樹視圖中的項目名稱。從TARGETS部分中選擇您的應用程序,然後選擇Info選項卡,然後展開URL Types部分。
    2. 單擊+按鈕,並為您的反向客戶端 ID 添加 URL 方案。要查找此值,請打開GoogleService-Info.plist配置文件,然後查找REVERSED_CLIENT_ID鍵。複製該鍵的值,並將其粘貼到配置頁面上的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的方式,請創建一個符合FIRAuthUIDelegate協議的自定義類。

  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 項目的一部分存儲,可用於在項目中的每個應用中識別用戶,無論用戶如何登錄。

  • 在您的應用程序中,您可以從FIRUser對象獲取用戶的基本個人資料信息。請參閱管理用戶

  • 在您的 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;
}

您可能還想為所有身份驗證錯誤添加錯誤處理代碼。請參閱處理錯誤