sign-in-with-google-web
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.
Savant verdict: Pending analysis
Imported from the source hub; Savant's analysis is still running.
Live evaluation
Not evaluated yet. Workspaces can request a live evaluation.
Security assessment
Scan pending.
Structure
- No license declaredConfirm you may reuse this skill before importing it into your repository.
SKILL.md
---
name: sign-in-with-google-web
metadata:
category: Identity
version: "1.0.0"
description: >-
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.
---
# 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`)](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#name-application-architecture-pa)
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](references/bff_fastapi_verification.md).
### 🚀 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](references/tmb_login_uri_redirect.md).
### 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](references/in_memory_spa_nonce.md).
### 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](references/offline_pwa_encryption.md).
--------------------------------------------------------------------------------
## 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](references/intermediate_iframe.md).
--------------------------------------------------------------------------------
## 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](references/bff_fastapi_verification.md)
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](references/tmb_login_uri_redirect.md)
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](references/in_memory_spa_nonce.md) 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](references/offline_pwa_encryption.md)
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](references/intermediate_iframe.md) 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
* [RFC 7519: JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519)
— Standard claims (`iss`, `sub`, `aud`, `exp`, `iat`, `nonce`), formatting,
and processing rules.
* [RFC 7515: JSON Web Signature (JWS)](https://datatracker.ietf.org/doc/html/rfc7515)
— Cryptographic signature verification against Google's public JWK certs
(`https://www.googleapis.com/oauth2/v3/certs`).
* [RFC 4648 § 5: Base64url Encoding](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
— URL-safe Base64 encoding without padding used across JWT segments.
* [IETF OAuth 2.0 Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps)
— Normative architecture standards (§ 6.1 BFF, § 6.2 TMB, § 6.3
Client-side).
* [Google Identity Services Web Reference](https://developers.google.com/identity/gsi/web/reference/js-reference)
— Official GIS API reference.
* [Intermediate Iframe API Reference](https://developers.google.com/identity/gsi/web/amp/nonamp-reference)
— Cross-origin iframe embedding guide.
* [Verify ID Tokens Server-Side](https://developers.google.com/identity/gsi/web/guides/verify-google-id-token)
— Server-side token verification protocols.
* [W3C Federated Credential Management API (FedCM)](https://www.w3.org/TR/fedcm-1/)
— Browser identity credential mediation standard.
* [W3C Web Cryptography API](https://www.w3.org/TR/WebCryptoAPI/) —
Non-extractable key generation (`extractable: false`) and AES-GCM standards.