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

在 Web 應用程序中使用 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 添加到您的 JavaScript 項目中。

  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 JavaScript SDK 處理登錄流程,請按以下步驟操作:

  1. 使用您在 Firebase 控制台中獲得的提供程序 ID 創建OAuthProvider的實例。

    Web version 9

    import { OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('oidc.example-provider');
    

    Web version 8

    var provider = new firebase.auth.OAuthProvider('oidc.example-provider');
    
  2. 可選:指定要隨 OAuth 請求一起發送的其他自定義 OAuth 參數。

    Web version 9

    provider.setCustomParameters({
      // Target specific email with login hint.
      login_hint: 'user@example.com'
    });
    

    Web version 8

    provider.setCustomParameters({
      // Target specific email with login hint.
      login_hint: 'user@example.com'
    });
    

    請與您的供應商核實其支持的參數。請注意,您不能使用setCustomParameters傳遞 Firebase 所需的參數。這些參數是client_idresponse_typeredirect_uristatescoperesponse_mode

  3. 可選:指定您希望從身份驗證提供程序請求的基本配置文件之外的其他 OAuth 2.0 範圍。

    Web version 9

    provider.addScope('mail.read');
    provider.addScope('calendars.read');
    

    Web version 8

    provider.addScope('mail.read');
    provider.addScope('calendars.read');
    

    請諮詢您的提供商以了解其支持的範圍。

  4. 使用 OAuth 提供程序對象向 Firebase 進行身份驗證。

    您可以將用戶重定向到提供商的登錄頁面或在彈出式瀏覽器窗口中打開登錄頁面。

    重定向流

    通過調用signInWithRedirect()重定向到提供者登錄頁面:

    Web version 9

    import { getAuth, signInWithRedirect } from "firebase/auth";
    
    const auth = getAuth();
    signInWithRedirect(auth, provider);
    

    Web version 8

    firebase.auth().signInWithRedirect(provider);
    

    用戶完成登錄並返回您的應用後,您可以通過調用getRedirectResult()獲取登錄結果。

    Web version 9

    import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
    
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    

    Web version 8

    firebase.auth().getRedirectResult()
      .then((result) => {
        // IdP data available in result.additionalUserInfo.profile.
        // ...
    
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // OAuth access and id tokens can also be retrieved:
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    

    彈出流

    Web version 9

    import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    signInWithPopup(auth, provider)
      .then((result) => {
        // User is signed in.
        // IdP data available using getAdditionalUserInfo(result)
    
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    

    Web version 8

    firebase.auth().signInWithPopup(provider)
      .then((result) => {
        // IdP data available in result.additionalUserInfo.profile.
        // ...
    
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // OAuth access and id tokens can also be retrieved:
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    
  5. 雖然上述示例側重於登錄流程,但您可以使用相同的模式使用linkWithRedirect()linkWithPopup()將 OIDC 提供程序鏈接到現有用戶,並使用 reauthenticateWithRedirect( reauthenticateWithRedirect()reauthenticateWithPopup() () 重新驗證用戶,可用於檢索需要最近登錄的敏感操作的新憑據。

手動處理登錄流程

如果您已經在應用中實現了 OpenID Connect 登錄流程,則可以直接使用 ID 令牌向 Firebase 進行身份驗證:

Web version 9

import { getAuth, signInWithCredential, OAuthProvider } from "firebase/auth";

const provider = new OAuthProvider("oidc.example-provider");
const credential = provider.credential({
    idToken: idToken,
});
signInWithCredential(getAuth(), credential)
    .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.

        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
    })
    .catch((error) => {
        // Handle error.
    });

Web version 8

const provider = new OAuthProvider("oidc.example-provider");
const credential = provider.credential({
    idToken: idToken,
});
firebase.auth().signInWithCredential(credential)
    .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.

        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
    })
    .catch((error) => {
        // Handle error.
    });