使用 SAML 进行身份验证(Web 应用)

如果您已升级到带有 Identity Platform 的 Firebase Authentication,则可以使用所选的 SAML 身份提供方通过 Firebase 验证用户身份。这样,您就可以使用基于 SAML 的单点登录解决方案让用户登录到您的 Firebase 应用。

Firebase Authentication 仅支持服务提供方启动的 SAML 流程。

准备工作

如需让用户使用 SAML 身份提供方登录,您必须先从该提供方处收集一些信息:

  • 提供方的实体 ID:用于标识身份提供方的 URI。
  • 提供方的 SAML 单点登录网址:身份提供方的登录页面的网址。
  • 提供方的公钥证书:用于验证身份提供方签署的令牌的证书。
  • 应用的实体 ID:用于标识应用(“服务提供方”)的 URI。

获得上述信息后,启用 SAML 作为 Firebase 项目的登录提供方:

  1. 将 Firebase 添加至您的 JavaScript 项目

  2. 如果您尚未升级到带有 Identity Platform 的 Firebase Authentication,请升级。SAML 身份验证仅适用于升级后的项目。

  3. 在 Firebase 控制台的登录提供方页面上,点击添加新提供方,然后点击 SAML

  4. 为此提供方命名。请记下系统生成的提供方 ID(类似于 saml.example-provider)。向应用添加登录代码时,您需要用到此 ID。

  5. 指定身份提供方的实体 ID、单点登录网址和公钥证书,以及应用(服务提供方)的实体 ID。这些值必须与提供方分配给您的值完全匹配。

  6. 保存更改。

  7. 如果您尚未向应用网域授权,请在 Firebase 控制台的 Authentication > 设置页面上将其添加到允许列表中。

使用 Firebase SDK 处理登录流程

如需使用 Firebase JavaScript SDK 处理登录流程,请按以下步骤操作:

  1. 使用您在 Firebase 控制台中获得的提供方 ID 创建 SAMLAuthProvider 实例。

    Web 模块化 API

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

    Web 命名空间型 API

    var provider = new firebase.auth.SAMLAuthProvider('saml.example-provider');
    ``
    
  1. 使用 SAML 提供方对象通过 Firebase 进行身份验证。

    您可以将用户重定向到提供方的登录页面,也可以在弹出式浏览器窗口中打开登录页面。

    重定向流程

    调用 signInWithRedirect() 重定向到提供方登录页面:

    Web 模块化 API

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

    Web 命名空间型 API

    firebase.auth().signInWithRedirect(provider);
    

    用户完成登录并返回到您的应用后,您可以调用 getRedirectResult() 获取登录结果。

    Web 模块化 API

    import { getAuth, getRedirectResult, SAMLAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        // User is signed in.
    
        // Provider data available using getAdditionalUserInfo()
      })
      .catch((error) => {
        // Handle error.
      });
    

    Web 命名空间型 API

    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.
      })
      .catch((error) => {
        // Handle error.
      });
    

    弹出式窗口流程

    Web 模块化 API

    import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    signInWithPopup(auth, provider)
      .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.
      })
      .catch((error) => {
        // Handle error.
      });
    

    Web 命名空间型 API

    firebase.auth().signInWithPopup(provider)
      .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.
      })
      .catch((error) => {
        // Handle error.
      });
    

    只有在身份提供方的 SAML 断言的 NameID 属性中提供了用户的电子邮件地址时,它才会包含在 ID 令牌和 UserInfo 对象中:

    <Subject>
      <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@email.com</NameID>
    </Subject>
    
  2. 以上示例侧重的是登录流程。除此之外,您也可以使用同一模式通过 linkWithRedirect()linkWithPopup() 将 SAML 提供方与现有用户相关联,然后使用 reauthenticateWithRedirect()reauthenticateWithPopup()(可用于为要求用户在近期登录的敏感操作检索新的凭据)重新验证用户身份。