透過 SAML 登入使用者

本文說明如何使用 Identity Platform,透過安全宣告標記語言 (SAML) 2.0 供應商登入使用者帳戶。

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. 啟用 Identity Platform,並將用戶端 SDK 新增至應用程式。如要瞭解做法,請參閱快速入門
  7. 設定提供者

    1. 前往 Google Cloud 控制台的「Identity Providers」(識別資訊提供者) 頁面。
      前往「Identity Providers」(識別資訊提供者) 頁面

    2. 按一下「新增供應商」,然後從清單中選取「SAML」

    3. 輸入下列詳細資訊:

      1. 供應商名稱。這可以與供應商 ID 相同,也可以是自訂名稱。如果輸入自訂名稱,請按一下「供應商 ID」旁的「編輯」,指定 ID (必須以 saml. 開頭)。

      2. 供應商的實體 ID

      3. 供應商的 SAML 單一登入網址

      4. 用於簽署提供者權杖的憑證。請務必加入開始和結束字串。例如:

        -----BEGIN CERTIFICATE-----
        MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czEL
        ...
        LEzc1JwEGQQVDYQCwsQMSBDAF0QAB0w9GikhqkgBNADABIgABIwAgOdACCjaCIIM
        -----END CERTIFICATE-----
        
    4. 在「服務供應商」下方,輸入應用程式的「實體 ID」。這通常是應用程式的網址。在 SAML 識別資訊提供者中,這稱為對象。

    5. 將應用程式新增至「已授權網域」清單。舉例來說,如果應用程式的登入網址為 https://example.com/login,請新增 example.com

    6. 視需要自訂應用程式的回呼網址。SAML 身分識別提供者通常將此網址稱為宣告客戶服務 (ACS) 網址。

      使用預設回呼網址可降低驗證 SAML 回應的複雜度。如果您自訂這個流程,請務必在 SAML 識別資訊提供者上,設定專案的 Identity Platform 回呼網址。這通常看起來像 https://[PROJECT-ID].firebaseapp.com/__/auth/handler。 詳情請參閱「自訂驗證處理常式」。

    7. 按一下 [儲存]

    供應商必要元素

    Identity Platform 預期供應商的回應中會包含 <saml:Subject><saml:NameID> 元素。 如果您在設定供應商時未定義這些元素的值,SAML 斷言就會失敗。

    簽署要求

    您可以簽署驗證要求,提高安全性。

    如要簽署要求,請先呼叫 inboundSamlConfigs.patch(),並將 idp_config.sign_request 設為 true,為身分識別資訊提供者啟用已簽署的要求:

    REST

    使用任何要求資料之前,請先替換以下項目:

    • project-id: Google Cloud 專案的 ID
    • provider-id:SAML 提供者 ID

    HTTP 方法和網址:

    PATCH https://identitytoolkit.googleapis.com/admin/v2/projects/project-id/inboundSamlConfigs/provider-id?updateMask=idpConfig.signRequest

    JSON 要求主體:

    {
      "idp_config": {
        "sign_request": true
      }
    }
    

    如要傳送要求,請展開以下其中一個選項:

     

    您必須使用 REST API 啟用已簽署的要求,不支援使用Google Cloud 控制台或 Google Cloud CLI。

    回應是 InboundSamlConfig 物件,其中包含 SpCertificate 陣列。向 SAML 識別資訊提供者設定 X509 憑證的值,以便驗證要求的簽章。

    登入的使用者

    登入使用者時,用戶端 SDK 會處理驗證交握,然後傳回 ID 權杖,其中包含酬載中的 SAML 屬性。如要登入使用者並從 SAML 提供者取得屬性,請按照下列步驟操作:

    1. 使用您在前一節中設定的供應商 ID,建立 SAMLAuthProvider 執行個體。提供者 ID 的開頭必須是 saml.

      網頁版 9

      import { SAMLAuthProvider } from "firebase/auth";
      
      const provider = new SAMLAuthProvider("saml.myProvider");

      網頁版 8

      const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');
    2. 啟動登入流程。你可以選擇使用彈出式視窗或重新導向。

      網頁版 9

      import { getAuth, signInWithPopup, SAMLAuthProvider } from "firebase/auth";
      
      const auth = getAuth();
      signInWithPopup(auth, provider)
        .then((result) => {
          // User is signed in.
          // Provider data available from the result.user.getIdToken()
          // or from result.user.providerData
        }).catch((error) => {
          // Handle Errors here.
          const errorCode = error.code;
          const errorMessage = error.message;
          // The email of the user's account used.
          const email = error.customData.email;
          // The AuthCredential type that was used.
          const credential = SAMLAuthProvider.credentialFromError(error);
          // Handle / display error.
          // ...
        });

      網頁版 8

      firebase.auth().signInWithPopup(provider)
        .then((result) => {
          // User is signed in.
          // Identity provider data available in result.additionalUserInfo.profile,
          // or from the user's ID token obtained from result.user.getIdToken()
          // as an object in the firebase.sign_in_attributes custom claim
          // This is also available from result.user.getIdTokenResult()
          // idTokenResult.claims.firebase.sign_in_attributes.
        })
        .catch((error) => {
          // Handle / display error.
          // ...
        });

      重新導向

      如要重新導向至登入頁面,請呼叫 signInWithRedirect()

      網頁版 9

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

      網頁版 8

      firebase.auth().signInWithRedirect(provider);

      接著,在使用者返回應用程式時呼叫 getRedirectResult() 取得結果:

      網頁版 9

      import { getAuth, getRedirectResult, SAMLAuthProvider } from "firebase/auth";
      
      const auth = getAuth();
      getRedirectResult(auth)
        .then((result) => {
          // User is signed in.
          // Provider data available from the result.user.getIdToken()
          // or from result.user.providerData
        })
        .catch((error) => {
          // Handle Errors here.
          const errorCode = error.code;
          const errorMessage = error.message;
          // The email of the user's account used.
          const email = error.customData.email;
          // The AuthCredential type that was used.
          const credential = SAMLAuthProvider.credentialFromError(error);
          // Handle / display error.
          // ...
        });

      網頁版 8

      firebase.auth().getRedirectResult()
        .then((result) => {
          // User is signed in.
          // Provider data available in result.additionalUserInfo.profile,
          // or from the user's ID token obtained from result.user.getIdToken()
          // as an object in the firebase.sign_in_attributes custom claim
          // This is also available from result.user.getIdTokenResult()
          // idTokenResult.claims.firebase.sign_in_attributes.
        }).catch((error) => {
          // Handle / display error.
          // ...
        });
    3. 使用 firebase.sign_in_attributes 聲明,從 ID 權杖擷取與 SAML 提供者相關聯的使用者屬性。請務必在將 ID 權杖傳送至伺服器時,使用 Admin SDK 驗證權杖。

      只有在身分識別提供者的 SAML 聲明中提供 NameID 屬性時,ID 權杖才會包含使用者的電子郵件地址:

      <Subject>
        <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@email.com</NameID>
      </Subject>
      

      這項資訊會填入 Firebase 簽發的 ID 權杖和 UserInfo 物件。

    目前僅支援從用戶端 SDK 啟動的服務供應商 SAML 流程。

    連結使用者帳戶

    如果使用者已透過其他方法 (例如電子郵件/密碼) 登入應用程式,您可以使用 linkWithPopup()linkWithRedirect() 將現有帳戶連結至 SAML 提供者: 舉例來說,我們可以連結 Google 帳戶:

    網頁版 9

    import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth";
    const provider = new GoogleAuthProvider();
    
    const auth = getAuth();
    linkWithPopup(auth.currentUser, provider).then((result) => {
      // Accounts successfully linked.
      const credential = GoogleAuthProvider.credentialFromResult(result);
      const user = result.user;
      // ...
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

    網頁版 8

    auth.currentUser.linkWithPopup(provider).then((result) => {
      // Accounts successfully linked.
      var credential = result.credential;
      var user = result.user;
      // ...
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

    後續步驟