使用 SAML 登录用户

本文档介绍如何使用 Identity Platform 让用户通过安全断言标记语言 (SAML) 2.0 提供方登录。

准备工作

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  5. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  6. 启用 Identity Platform,并将 Client SDK 添加到您的应用。如需了解具体方法,请参阅快速入门

配置提供商

  1. 转到 Cloud Console 中的 身份提供商页面。
    转到“身份提供商”页面

  2. 点击添加提供商,然后从列表中选择 SAML

  3. 输入以下详细信息:

    1. 提供商的名称。它可以与提供商 ID 相同,也可以是自定义名称。如果要输入自定义名称,请点击提供商 ID 旁边的修改以指定 ID(必须以 saml. 开头)。

    2. 提供商的实体 ID

    3. 提供商的 SAML SSO 网址

    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://<authDomain>/__/auth/handler。如需了解详情,请参阅自定义身份验证处理程序

  7. 点击保存

对请求进行签名

您可以通过对身份验证请求进行签名来增强其安全性。

要对请求进行签名,首先需要为您的身份提供商启用签名请求,方法是调用 inboundSamlConfigs.patch() 并将 idp_config.sign_request 设置为 true

REST

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 启用签名请求;不支持使用 Cloud Console 或 gcloud 命令行工具。

响应是一个 InboundSamlConfig 对象,它包含一组 SpCertificate。 使用您的 SAML 身份提供商配置 X509 证书的值,以便它能够验证请求的签名。

登录用户

当用户登录时,Client SDK 会处理身份验证握手,然后返回载荷中包含 SAML 特性的 ID 令牌。要登录用户并从 SAML 提供商获取特性,请执行以下操作:

  1. 使用您在上一部分中配置的提供商 ID 创建 SAMLAuthProvider 实例。提供商 ID 必须以 saml. 开头。

    const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');
    
  2. 启动登录流程。您可以选择使用弹出式窗口或重定向。

    要显示弹出式窗口,请调用 signInWithPopup()

    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 error.
      });
    

    重定向

    要重定向到登录页面,请调用 signInWithRedirect()

    firebase.auth().signInWithRedirect(provider);
    

    然后,调用 getRedirectResult() 以在用户返回应用时获取结果:

    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 error.
      });
    
  3. 使用 firebase.sign_in_attributes 声明从 ID 令牌中检索与 SAML 提供商相关的用户特性。在将 ID 令牌 发送到服务器时,务必使用 Admin SDK 验证 ID 令牌。

目前仅支持服务提供商通过 Client SDK 启动的 SAML 流程。

关联用户帐号

如果用户已使用其他方法(例如电子邮件/密码)登录到应用,您可以使用 linkWithPopup()linkWithRedirect() 将其现有帐号关联到 SAML 提供商。例如:

const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');

// Link with a popup.
firebase.auth().currentUser.linkWithPopup(provider)
    // currentUser.providerData now has an additional entry for this provider.
  }).catch((error) => {
    // Handle error.
  });

重新验证用户身份

某些敏感操作(例如更新用户的电子邮件或密码)要求用户最近登录过。如需让用户重新登录,请调用 reauthenticateWithPopup()reauthenticateWithRedirect()。例如:

const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');

// Reauthenticate with a popup.
firebase.auth().currentUser.reauthenticateWithPopup(provider)
  .then((result) => {
    // Get the updated ID token.
    return result.user.getIdTokenResult();
  })
  .then((idTokenResult) => {
    // idTokenResult.authTime should be updated to reflect recent sign-in status.
    // idTokenResult.token has the latest ID token.
  })
  .catch((error) => {
    // Handle error.
  });

后续步骤