使用 iframe 集成一键快捷功能

Google One Tap 可在由您自己的网站托管的 iframe(以下简称“中间 iframe”)中呈现。使用中间 iframe 时,一键式体验不会有任何明显变化。

基于 iframe 的中间集成带来了一些灵活性和风险:

  • 适用于一键式登录和后续用户体验流程的内嵌用户体验

    一键式体验完成后,您可以在中间 iframe 中显示后续的用户体验流程。因此,一键式登录和后续用户体验都可以嵌入到当前内容页面中。以下是一个示例。

    包含中间 iframe 的嵌入式用户体验示例。

    如果没有中间 iframe,通常需要全页导航才能显示后续的用户体验流程,这在某些情况下可能会造成干扰。

  • 集成一次,随处展示

    所有 One Tap 集成代码(One Tap API 调用和后续的用户体验处理)都封装在中间 iframe 中。在可能显示一键式登录的网页上,您只需嵌入中间 iframe 即可。

    这种架构允许分离关注点,从而降低集成和维护成本。

  • 限制 ID 令牌的公开范围

    ID 令牌会被中间 iframe 直接使用。这些信息绝不会显示在内容页面上。这种架构可能会大大缩小 ID 令牌的公开范围。

    中间 iframe 方法也适用于已拥有专门的登录相关子网域(例如 login.example.com)和多个内容相关子网域(例如 sports.example.com 和 games.example.com)的网站。

  • 一键显示网域

    根据 Google 的 OAuth 政策,所有接收 OAuth 响应的网域都需要在 Google Cloud 控制台中预先注册。在正常的 One Tap 集成中,开发者需要预先注册 One Tap 可能会显示的所有网域,因为 ID 令牌将传回给这些网域。某些网站允许用户动态创建子网域,而这些子网域是无法预先注册的。因此,这些动态创建的子网域中无法显示一键式登录。

    您可以利用中间 iframe 来解决此问题。在这种情况下,只需预注册中间 iframe 的域名即可。无需注册内容页域名,因为 ID 令牌不会向这些内容页面公开。

  • 隐私风险

    开发者必须采取措施,防止中间 iframe 嵌入到意外网域中。例如,malicious.com 可能会嵌入您的中间 iframe,从而在其网站上显示您的一键式体验。这肯定会引起最终用户的许多隐私问题。

  • 安全风险

    由于上述意外嵌套问题,中间 iframe 绝不应向其父级框架发送安全或隐私敏感数据,例如 ID 令牌、会话 Cookie 值、用户数据等。如果违反此规则,您的网站可能会面临危险。

在中间 iframe 中呈现一键式付款

如需在中间 iframe 中显示一键式登录,请将以下代码段放入中间 iframe 的 HTML 代码中:

<div id="g_id_onload"
     data-client_id="YOUR_GOOGLE_CLIENT_ID"
     data-login_uri="https://your.domain/your_login_endpoint"
     data-allowed_parent_origin="https://example.com">
</div>

如果使用 data-allowed_parent_origin 属性,Google One Tap 将在中间 iframe 模式下运行。您可以将一个网域或以英文逗号分隔的网域列表设置为属性值。通配符子网域也受支持。

在跨源 iframe 中将 One Tap 与 FedCM 集成

从跨源 iframe 调用 One Tap API 时,如果您的应用从跨源 iframe 调用 One Tap API,您必须向所有级别的父级框架添加 allow="identity-credentials-get" 属性。如果您的应用使用 Intermediate Iframe API 嵌入 One Tap,则无需其他属性,因为它支持 FedCM 跨源 iframe。不过,如果您使用 Intermediate Iframe API 在另一个 iframe 中嵌入页面,则必须将该属性添加到所有父级 iframe。

如果 iframe 的 origin 与父 origin 不完全相同,则会被视为跨源。例如:

  • 不同的网域:https://example1.comhttps://example2.com
  • 不同的顶级域名:https://example.ukhttps://example.jp
  • 子网域:https://example.comhttps://login.example.com

在跨源 iframe 中使用一键式登录时,用户可能会遇到令人困惑的体验。为了防止凭据盗用,一键式登录提示会显示顶级网域的名称,而不是 iframe 的名称。不过,ID 令牌会颁发给 iframe 的来源。如需了解详情,请参阅此 GitHub 问题

由于这种差异可能会造成误导,因此仅在跨源但同网站 iframe 中使用一键式登录是一种受支持的方法。例如,顶级域名 https://www.example.com 上的某个网页使用 iframe 嵌入了 https://login.example.com 上的 One Tap 页面。一键登录提示将显示“使用 google.com 登录 example.com”。

所有其他情况(例如不同的网域)均不受支持。请改为考虑其他集成方法,例如:

  • 实现“使用 Google 账号登录”按钮
  • 在顶级域名上实现一键式登录
  • 利用 Google OAuth 2.0 端点实现更个性化的集成。
  • 如果您要在 iframe 中嵌入第三方网站,但无法修改其“一键式”验证实施方式,则可以阻止“一键式”验证提示显示在 iframe 中。为此,请从父级框架中的 iframe 标记中移除 allow="identity-credentials-get" 属性。这会禁止显示提示,然后您可以直接引导用户前往嵌入的网站的登录页面。

(可选)在中间 iframe 中呈现后续用户体验

在登录响应中,您可以返回任何 HTML 代码,该代码可能会向最终用户显示一些可见内容。例如,要求提供额外的个人资料信息或同意服务条款。提交页面后,您可以显示其他页面。 例如,付款或订阅。

您可以调整中间 iframe 的大小:

<script src="https://accounts.google.com/gsi/intermediatesupport"></script>
<script>
  google.accounts.id.intermediate.notifyParentResize(320);
</script>

总而言之,借助中间 iframe,完整的登录或注册体验流程可以作为嵌入式体验来实现。

对于一键式体验后的第一个页面,您需要调用 notifyParentResize() 方法两次,原因如下。

  1. 一键式体验完成后,中间 iframe 会设为隐藏。

  2. 元素处于隐藏状态时,其 offsetHeight 属性值为 0。

在第一次调用中,您可以将 iframe 高度调整为 1px,以使其可见。然后,在 offsetHeight 属性值可用后,您可以将其调整为合适的高度。

以下示例代码展示了如何在“一键式”用户体验后验证父级源并调整界面中中间 iframe 的大小。

<script>
window.onload = () => {
  google.accounts.id.intermediate.verifyParentOrigin(
    ["https://example.com","https://example-com.cdn.ampproject.org"],
    () => {
      google.accounts.id.intermediate.notifyParentResize(1);
      window.setTimeout(() => {
        let h = document.getElementById('container').offsetHeight;
        google.accounts.id.intermediate.notifyParentResize(h);
      }, 200);
    },
    () => {
      document.getElementById('container').style.display = 'none';
      document.getElementById('warning').innerText = 'Warning: the page is displayed in an unexpected domain!';
    }
  );
};
</script>

移除了“用户体验完成”中的中间 iframe

在用户体验流程完成后,您必须通知父级内容页面移除中间 iframe。为此,您可以在登录响应代码中放置以下代码段。

<script src="https://accounts.google.com/gsi/intermediatesupport"></script>
<script>
  google.accounts.id.intermediate.notifyParentDone();
</script>

如果跳过用户体验流程,则需要改为调用 notifyParentClose 方法。

将中间 Iframe 嵌入到 HTML 页面中

将以下代码段放置在您希望 Google One Tap 显示的任何 HTML 网页中:

<script src="https://accounts.google.com/gsi/intermediate"></script>
<div id="g_id_intermediate_iframe"
     data-src="https://example.com/onetap_iframe.html">
</div>

data-src 属性是您的中间 iframe 的 URI。