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.
<!-- mdformat off(reason: preserve ASCII architecture diagram width) --> <!-- mdformat on -->[!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.
🏆 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) viafetch('/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 theaud,hd, andnonceclaims against server session state, creates a server session, and issues a first-partyHttpOnly; Secure; SameSite=Laxsession 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"anddata-ux_mode="redirect"). -
Backend Responsibilities: The backend receives the ID token as a form POST body (
credentialparameter), validates the double-submitg_csrf_tokencookie against theg_csrf_tokenPOST 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
localStorageorsessionStorage. -
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
nonceviawindow.crypto.getRandomValues()and pass it directly togoogle.accounts.id.initialize({ client_id, nonce: clientNonce }). Validate thatpayload.nonce === clientNoncebefore 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 WebCryptoAES-GCMwith a non-extractable session key (extractable: false) before writing ciphertext and IV toIndexedDB. -
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
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:
(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: trueingoogle.accounts.id.initialize({...})(do not pass the deprecateduse_fedcm_for_promptparameter). -
Deprecated Library Warning: NEVER mix deprecated
gapi.auth2(gapi.auth2.init,gapi.auth2.getAuthInstance().signOut()) with Google Identity Services (GIS).gapi.auth2is 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(): -
(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.idbefore<script src="https://accounts.google.com/gsi/client">has finished loading causesReferenceError: google is not defined. -
NEVER use
gapior polling (setInterval): Use deterministic dynamic script loading withonload/addEventListener('load')event listeners. -
Dynamic Script Loader Pattern:
-
(Always use deterministic
onloadevent listeners or framework<Script strategy="afterInteractive">rather than brittlesetIntervalpolling).
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:
(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(), orgapi.signin2. Always warn thatgapi.auth2is deprecated and decommissioned. -
GIS (
google.accounts.id.*andgoogle.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_tokencryptographic verification,noncereplay checks, Google Workspacehddomain enforcement, andHttpOnly; Secure; SameSite=Laxsession cookie issuance. -
Recipe 2 — Pattern B (Token-Mediating Backend with
login_uriForm POST Redirect) [RECOMMENDED]: Load references/tmb_login_uri_redirect.md [blocked] fordata-login_uri/ux_mode: 'redirect'frontend setup and FastAPI double-submitg_csrf_tokencookie 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
noncegeneration (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-GCMCryptoKeygeneration and encryptedIndexedDBstorage. -
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 strictwindow.postMessageorigin verification.
5. Sign-Out & Account Revocation Across All Patterns
6. References & Normative Standards
-
RFC 7519: JSON Web Token (JWT) — Standard claims (
iss,sub,aud,exp,iat,nonce), formatting, and processing rules. -
RFC 7515: JSON Web Signature (JWS) — Cryptographic signature verification against Google's public JWK certs (
https://www.googleapis.com/oauth2/v3/certs). -
RFC 4648 § 5: Base64url Encoding — URL-safe Base64 encoding without padding used across JWT segments.
-
IETF OAuth 2.0 Browser-Based Applications — Normative architecture standards (§ 6.1 BFF, § 6.2 TMB, § 6.3 Client-side).
-
Google Identity Services Web Reference — Official GIS API reference.
-
Intermediate Iframe API Reference — Cross-origin iframe embedding guide.
-
Verify ID Tokens Server-Side — Server-side token verification protocols.
-
W3C Federated Credential Management API (FedCM) — Browser identity credential mediation standard.
-
W3C Web Cryptography API — Non-extractable key generation (
extractable: false) and AES-GCM standards.


