使用 iframe 整合 One Tap

Google One Tap 可在您網站代管的 iframe (以下稱為中介 iframe) 中算繪。使用中介 iframe 時,One Tap 使用者體驗不會有任何可察覺的變化。

以 iframe 為基礎的中介整合方式可帶來一些彈性和風險:

  • One Tap 和後續使用者體驗流程的內嵌使用者體驗

    完成 One Tap UX 後,您可以在中介 iframe 中顯示後續 UX 流程。因此,One Tap 和後續使用者體驗都能嵌入目前的內容頁面。請參閱下方的範例。

    內嵌使用者體驗 (含中介 iframe) 示例。

    如果沒有中介 iframe,通常需要全頁導覽才能顯示後續的使用者體驗流程,但在某些情況下,這可能會造成干擾。

  • 整合一次,隨處顯示

    所有 One Tap 整合程式碼 (One Tap API 叫用和後續的使用者體驗處理) 都會封裝在中繼 iframe 中。在可能顯示 One Tap 的內容頁面中,您只需嵌入中介 iframe 即可。

    這種架構可分離各項關切事項,因此可降低整合和維護成本。

  • 限制 ID 權杖曝光範圍

    ID 權杖會直接由中繼 iframe 使用。這些內容不會顯示在內容頁面上。這種架構可能會大幅降低 ID 權杖的曝光範圍。

    中階 iframe 方法也適用於已設有專屬登入相關子網域 (例如 login.example.com) 和多個內容相關子網域 (例如 sports.example.com 和 games.example.com) 的網站。

  • One Tap 顯示網域

    根據 Google 的 OAuth 政策規定,所有接收 OAuth 回應的網域都必須先在 Google Cloud 控制台註冊。在一般 One Tap 整合作業中,開發人員需要預先註冊 One Tap 可能顯示的所有網域,因為 ID 權杖會傳回這些網域。部分網站允許使用者動態建立子網域,因此無法預先註冊。因此,One Tap 無法顯示在這些動態建立的子網域中。

    您可以利用中繼 iframe 解決這個問題。在這種情況下,您只需要預先註冊中介 iframe 的網域。由於 ID 權杖不會公開給這些內容網頁,因此不需要註冊內容網頁網域。

  • 隱私權風險

    開發人員必須採取措施,避免中繼 iframe 嵌入非預期的網域。舉例來說,malicious.com 可能會嵌入您的中介 iframe,並在其網站上顯示 One Tap 使用者體驗。這肯定會引起使用者對隱私權的疑慮。

  • 安全性風險

    由於上述意外的框架問題,中介 iframe 絕不應將安全性或隱私權敏感資料傳送至其上層框架,例如 ID 權杖、工作階段 cookie 值、使用者資料等。如果違反這項規則,可能會使網站面臨危險。

在中介 iframe 中轉譯 One Tap

如要在中繼 iframe 中顯示 One Tap,請將下列程式碼片段放入中繼 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,由於該 API 支援 FedCM 跨來源 iframe,因此不需要額外屬性。不過,如果您使用 Intermediate Iframe API 在另一個 iframe 中嵌入網頁,則必須將屬性新增至所有上層 iframe。

如果 iframe 的來源與父來源不完全相同,就會視為跨來源。例如:

  • 不同網域:https://example1.comhttps://example2.com
  • 不同的頂層網域:https://example.ukhttps://example.jp
  • 子網域:https://example.comhttps://login.example.com

在跨來源 iframe 中使用 One Tap 時,使用者可能會遇到混淆的體驗。為了防止盜用憑證,One Tap 提示會顯示頂層網域名稱,而非 iframe 名稱。不過,ID 權杖會發送至 iframe 的來源。詳情請參閱這項 GitHub 問題

由於這項差異可能會造成誤解,因此支援的做法是只在跨來源但同網站的 iframe 中使用 One Tap。舉例來說,頂層網域 https://www.example.com 上的網頁使用 iframe 嵌入 https://login.example.com 上的 One Tap 網頁。One Tap 提示會顯示「使用 google.com 登入 example.com」。

其他所有情況 (例如不同網域) 均不支援。請改用其他整合方法,例如:

  • 導入「使用 Google 帳戶登入」按鈕
  • 在頂層網域上實作 One Tap
  • 使用 Google OAuth 2.0 端點,進一步自訂整合作業。
  • 如果您要在 iframe 中嵌入第三方網站,但無法修改其 One Tap 導入方式,可以防止 One Tap 提示訊息顯示在 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,完整的登入或註冊使用者體驗流程可做為嵌入式使用者體驗導入。

針對 One Tap UX 後的第一個頁面,您需要呼叫 notifyParentResize() 方法兩次,原因如下:

  1. 當 One Tap 使用者介面完成時,中繼 iframe 會設為隱藏。

  2. 元素隱藏時,其 offsetHeight 屬性值為 0。

在第一次呼叫時,您可以將 iframe 高度調整為 1 px,讓 iframe 顯示出來。接著,在 offsetHeight 屬性值可用後,您可以將其調整為適當的高度。

以下程式碼範例說明如何驗證父項來源,並在 One Tap UX 後為 UI 調整中介 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>

移除 UX Done 中的中繼 Iframe

您必須在 UX 流程結束時,通知父項內容頁面移除中繼 iframe。為此,您可以在登入回應程式碼中放入下列程式碼片段。

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

如果略過 UX 流程,則需要改為呼叫 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。