Google One Tap 可在由您自己的网站托管的 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.com
和https://example2.com
- 不同的顶级域名:
https://example.uk
和https://example.jp
- 子网域:
https://example.com
和https://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()
方法两次,原因如下。
一键式体验完成后,中间 iframe 会设为隐藏。
元素处于隐藏状态时,其
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。