Sign In With Google Web

google/skills/skills/identity/sign-in-with-google-web

作者 googlec6c7e67107f02e3423df8481272f296bbe61902a無授權條款21K 個星標收錄於 2026年10月9日更新於 2026年10月9日儲存庫今天更新

Implement, configure, and secure Sign In With Google (SiwG) using Google Identity Services (GIS / `https://accounts.google.com/gsi/client`) across web architectures. Use when creating Google sign-in buttons, implementing Google One Tap with FedCM, integrating GIS in React/Next.js/Angular/HTML, verifying ID tokens on backend runtimes (Python/Node.js/Go/Java), enforcing Google Workspace domain restrictions (`hd`), securing client-side ID tokens via WebCrypto nonces or encrypted IndexedDB, embedding in cross-origin iframes via the Intermediate Iframe API (`https://accounts.google.com/gsi/intermediate`), configuring Content Security Policy (CSP), COOP, and Permissions Policy (`identity-credentials-get`) headers, or handling sign-out and revocation. Don't use for legacy Google Sign-In (`gapi.auth2`), Google Cloud IAM service accounts, or Android/iOS native Credential Manager.

AI 產生的概覽

為各種 Web 架構提供 Sign In With Google(GIS)整合與安全實作的指引。

功能
此技能提供透過 Google Identity Services Web SDK 整合 Sign In With Google 的規範性架構指引與實作契約。內容涵蓋四種符合 IETF 標準的模式:Backend For Frontend、透過 login_uri 重新導向的權杖中介後端、僅在瀏覽器記憶體中保存權杖的用戶端,以及適用於離線 PWA 的 WebCrypto 加密 IndexedDB 方案。同時規定必要的 CSP、COOP 與 Permissions Policy 標頭、登出與授權撤銷流程,並禁止使用舊版 gapi.auth2。參考檔案依模式提供具體實作範例。
適用情境
適用於在 Web 應用程式加入 Google 登入按鈕或搭配 FedCM 的 One Tap、在後端驗證 ID 權杖、限制僅特定 Google Workspace 網域登入、在跨來源 iframe 中嵌入登入,以及處理登出與帳號授權撤銷。不適用於舊版 Google Sign-In、Google Cloud IAM 服務帳戶或 Android/iOS 原生 Credential Manager。
執行需求
不含指令碼,僅提供說明與參考文件。實際實作需要 Web 前端,視情況需要後端執行環境(Python、Node.js、Go 或 Java)進行權杖驗證,以及連線至 Google Identity Services 與 Google 公開 JWK 憑證的網路存取。

Sign In With Google (SiwG) Integration & Security Architecture

This skill provides normative architectural guidelines, secure implementation contracts, and failure-prevention protocols for integrating Sign In With Google via the Google Identity Services (GIS) Web SDK (https://accounts.google.com/gsi/client).

1. IETF Architecture Taxonomy & Hierarchy (RECOMMEND BFF / TMB FIRST)

All Sign In With Google implementations MUST align with the IETF OAuth 2.0 for Browser-Based Applications (draft-ietf-oauth-browser-based-apps) taxonomy.

[!IMPORTANT] Primary Recommendation: Always recommend backend-mediated patterns (Pattern A: Backend For Frontend or Pattern B: Token-Mediating Backend / Redirect Mode) as the most secure, robust, and industry-standard architectures whenever an application has a backend server. Fall back to client-only browser patterns (Patterns C & D) only when constrained by serverless static hosting or offline-first PWA requirements.

<!-- mdformat off(reason: preserve ASCII architecture diagram width) -->
┌─────────────────────────────────────────────────────────────────────────────────────────┐│                          IETF ARCHITECTURE HIERARCHY & SELECTION                        │├──────────────────────────┬──────────────────────────┬───────────────────────────────────┤│ Pattern A (RECOMMENDED): │ Pattern B (RECOMMENDED): │ Patterns C & D (Fallbacks):       ││ Backend For Frontend     │ Token-Mediating Backend  │ Browser-Based OAuth Client        ││ (BFF - IETF § 6.1)       │ (TMB / Redirect § 6.2)   │ (JavaScript-Only - IETF § 6.3)    │├──────────────────────────┼──────────────────────────┼───────────────────────────────────┤│ 🏆 GOLD STANDARD         │ 🚀 NATIVE FORM REDIRECT  │ ⚡ STATIC SPA / 💾 OFFLINE PWA    ││ • Full-stack SPA + API   │ • Server-rendered & apps │ • Pure client-side or offline PWAs││ • Client JS fetch to API │ • GIS HTTP POST login_uri│ • C: Ephemeral in-memory closure  ││ • HttpOnly session cookie│ • Direct server redirect │ • D: WebCrypto Encrypted IndexedDB││ • Tokens never in browser│ • Tokens never in JS     │ • Strict WebCrypto nonces / keys  │└──────────────────────────┴──────────────────────────┴───────────────────────────────────┘
<!-- mdformat on -->

🏆 Pattern A: Backend For Frontend (BFF - IETF § 6.1) — STRONGLY RECOMMENDED

  • Why it is the Gold Standard: ID tokens (JWTs) and access tokens are never exposed to browser JavaScript across page reloads. This provides complete architectural immunity against XSS token harvesting.

  • Architecture: The browser frontend loads the GIS SDK, captures the credential in JavaScript callback (callback: handleCredentialResponse), and immediately forwards the ID token (JWT) via fetch('/api/auth/google', { method: 'POST' }) to the backend.

  • Backend Responsibilities: The backend validates the JWT cryptographic signature against Google's public JWKs (google.oauth2.id_token.verify_oauth2_token), checks the aud, hd, and nonce claims against server session state, creates a server session, and issues a first-party HttpOnly; Secure; SameSite=Lax session cookie.

  • See full implementation in references/bff_fastapi_verification.md [blocked].

🚀 Pattern B: Token-Mediating Backend via login_uri Redirect (IETF § 6.2) — Server-Rendered & Form POST

  • Why it is Highly Secure: Bypasses client-side JavaScript credential handling entirely by instructing GIS to perform an HTTP POST directly to the backend's login_uri.

  • Architecture: Configured via google.accounts.id.initialize({ client_id, login_uri: "https://example.com/api/auth/callback", ux_mode: "redirect" }) or HTML attributes (data-login_uri="https://example.com/api/auth/callback" and data-ux_mode="redirect").

  • Backend Responsibilities: The backend receives the ID token as a form POST body (credential parameter), validates the double-submit g_csrf_token cookie against the g_csrf_token POST body field, cryptographically verifies the ID token server-side, establishes a session cookie, and returns a standard HTTP 302/303 redirect.

  • See full implementation in references/tmb_login_uri_redirect.md [blocked].

Pattern C: Browser-Based OAuth Client — Ephemeral In-Memory (IETF § 6.3) — Fallback for Static SPAs

  • Scope: Use ONLY when deployment is strictly serverless/static (e.g., GitHub Pages, Firebase static hosting) with no backend component.

  • Storage Invariant: The ID token is held strictly in private JavaScript memory/closures during the active tab session. Never store raw tokens in localStorage or sessionStorage.

  • Session Renewal: Uses GIS One Tap / FedCM auto-select (auto_select: true) to transparently re-acquire fresh ID tokens into memory on page reload without persistent browser storage.

  • XSS & Replay Protection: Generate a cryptographic nonce via window.crypto.getRandomValues() and pass it directly to google.accounts.id.initialize({ client_id, nonce: clientNonce }). Validate that payload.nonce === clientNonce before trusting claims in memory.

  • See full implementation in references/in_memory_spa_nonce.md [blocked].

Pattern D: Browser-Based OAuth Client — WebCrypto Encrypted IndexedDB (IETF § 6.3) — Fallback for Offline PWAs

  • Scope: Use ONLY for offline-first Progressive Web Apps (PWAs) where user authentication proof must survive tab refreshes when disconnected from the network.

  • Storage Invariant: NEVER store raw plaintext ID tokens in localStorage. Encrypt the ID token payload using WebCrypto AES-GCM with a non-extractable session key (extractable: false) before writing ciphertext and IV to IndexedDB.

  • See full implementation in references/offline_pwa_encryption.md [blocked].


2. Mandatory Security Directives & Browser Policies

To avoid multi-turn repair loops and browser security exceptions, provide all required CSP, COOP, and user activation directives in the initial deliverable:

A. Content Security Policy (CSP) Directives

http
Content-Security-Policy:  script-src 'self' https://accounts.google.com/gsi/client;  frame-src https://accounts.google.com/gsi/;  connect-src https://accounts.google.com/gsi/;

If using strict nonce-based CSP, attach the nonce to the GIS script tag: <script src="https://accounts.google.com/gsi/client" async defer nonce="{{NONCE}}"></script>.

B. Cross-Origin Opener Policy (COOP)

To allow GIS popup dialogs to communicate credentials back to the parent window via postMessage:

http
Cross-Origin-Opener-Policy: same-origin-allow-popups

(Serving same-origin without allow-popups breaks GIS popups and results in silent failures).

C. Automatic Selection, FedCM, & Sign-Out Lifecycle (disableAutoSelect)

When enabling automatic zero-click return sign-in with Google One Tap (FedCM is enabled by default in GIS):

  • Set auto_select: true in google.accounts.id.initialize({...}) (do not pass the deprecated use_fedcm_for_prompt parameter).

  • Deprecated Library Warning: NEVER mix deprecated gapi.auth2 (gapi.auth2.init, gapi.auth2.getAuthInstance().signOut()) with Google Identity Services (GIS). gapi.auth2 is completely retired; use GIS methods exclusively.

  • Sign-Out Protocol: When the user explicitly logs out of your application, you MUST call google.accounts.id.disableAutoSelect():

    javascript
    function handleUserLogout() {  // 1. Disable automatic One Tap / FedCM re-authentication  google.accounts.id.disableAutoSelect();
      // 2. Clear application session state / server cookie  fetch('/api/auth/logout', { method: 'POST' }).then(() => {    window.location.href = '/login';  });}
  • (Failing to call disableAutoSelect() causes an immediate automatic re-login loop on the next page visit after intentional user logout).

D. Reliable Dynamic Script Loading & Framework Lifecycle (React, Next.js, SPAs)

When mounting Sign In With Google in Single Page Applications (React, Next.js, Vue, Angular):

  • Modern SPAs execute component lifecycles asynchronously. Attempting to access window.google.accounts.id before <script src="https://accounts.google.com/gsi/client"> has finished loading causes ReferenceError: google is not defined.

  • NEVER use gapi or polling (setInterval): Use deterministic dynamic script loading with onload / addEventListener('load') event listeners.

  • Dynamic Script Loader Pattern:

    tsx
    import React, { useEffect, useState } from 'react';
    export function useGoogleIdentityScript() {  const [isLoaded, setIsLoaded] = useState(false);
      useEffect(() => {    if (window.google?.accounts?.id) {      setIsLoaded(true);      return;    }
        const existingScript = document.querySelector(      'script[src="https://accounts.google.com/gsi/client"]'    );    if (existingScript) {      existingScript.addEventListener('load', () => setIsLoaded(true));      return;    }
        const script = document.createElement('script');    script.src = 'https://accounts.google.com/gsi/client';    script.async = true;    script.defer = true;    script.onload = () => setIsLoaded(true);    document.head.appendChild(script);  }, []);
      return isLoaded;}
  • (Always use deterministic onload event listeners or framework <Script strategy="afterInteractive"> rather than brittle setInterval polling).

E. Embedded Iframes & Permissions Policy (identity-credentials-get)

When embedding Sign In With Google or One Tap inside cross-origin <iframe> elements or widget integrations, modern browser security models and FedCM require explicit Permissions Policy delegation on the container frame:

html
<iframe  src="https://example.com/embed"  allow="identity-credentials-get 'src' https://accounts.google.com"></iframe>

(Omitting allow="identity-credentials-get" blocks FedCM / One Tap initialization inside embedded or cross-origin contexts). See full integration guide in references/intermediate_iframe.md [blocked].


3. Implementation Contracts & Anti-Pattern Bans

A. Strict Ban on Legacy GAPI (gapi.auth2)

  • NEVER import or reference gapi.auth2, gapi.auth2.init, gapi.auth2.getAuthInstance(), or gapi.signin2. Always warn that gapi.auth2 is deprecated and decommissioned.

  • GIS (google.accounts.id.* and google.accounts.oauth2.*) is completely stateless. It replaces all legacy GAPI authentication libraries.


4. Implementation Recipes (Progressive Disclosure)

Load the specific reference file matching your target architecture when generating implementation code:

  • Recipe 1 — Pattern A (Backend For Frontend with Python / FastAPI) [RECOMMENDED]: Load references/bff_fastapi_verification.md [blocked] for custom UI button prompting, google.oauth2.id_token.verify_oauth2_token cryptographic verification, nonce replay checks, Google Workspace hd domain enforcement, and HttpOnly; Secure; SameSite=Lax session cookie issuance.

  • Recipe 2 — Pattern B (Token-Mediating Backend with login_uri Form POST Redirect) [RECOMMENDED]: Load references/tmb_login_uri_redirect.md [blocked] for data-login_uri / ux_mode: 'redirect' frontend setup and FastAPI double-submit g_csrf_token cookie vs. form-body validation.

  • Recipe 3 — Pattern C (Browser-Based Ephemeral In-Memory SPA with Native GIS Nonce) [Fallback]: Load references/in_memory_spa_nonce.md [blocked] for WebCrypto nonce generation (google.accounts.id.initialize({ client_id, nonce: clientNonce })), UTF-8 safe Base64URL JWT decoding, and private closure token management.

  • Recipe 4 — Pattern D (Browser-Based WebCrypto Encrypted IndexedDB for Offline PWAs) [Fallback]: Load references/offline_pwa_encryption.md [blocked] for non-extractable (extractable: false) AES-GCM CryptoKey generation and encrypted IndexedDB storage.

  • Recipe 5 — Embedded Cross-Origin Contexts (gsi/intermediate): Load references/intermediate_iframe.md [blocked] for <div id="g_id_intermediate_iframe">, allow="identity-credentials-get", and strict window.postMessage origin verification.


5. Sign-Out & Account Revocation Across All Patterns

javascript
export function handleSignOut(userEmail) {  // 1. Disable client-side One Tap auto-selection  google.accounts.id.disableAutoSelect();
  // 2. Revoke OAuth grant if user disconnected account  if (userEmail) {    google.accounts.id.revoke(userEmail, () => {      console.log('User grant revoked');    });  }
  // 3. Clear storage / session  AuthManager.clear(); // Pattern C  fetch('/api/auth/logout', { method: 'POST' }); // Pattern A}

6. References & Normative Standards

來源與署名

來源:google/skills位於skills/identity/sign-in-with-google-web提交c6c7e67

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架