sign-in-with-google-web について
sign-in-with-google-webは、Google Identity Services Web SDKを使ったSign In With Googleの安全な統合を案内するエージェントスキルです。バックエンド仲介型とブラウザーのみの構成、セキュリティポリシー、セッション管理、Webアプリの実装パターンを扱います。
主な機能
- 01BFF、トークン仲介型、ブラウザーのみの構成を比較
- 02IDトークン検証とセッション管理を説明
- 03CSP、COOP、iframeのポリシーを提示
- 04SPAでのGISスクリプト読み込みを案内
- 05サインアウトと自動サインインの動作を説明
活用シーン
- 01Webアプリの認証アーキテクチャを選定
- 02サーバー側のIDトークン検証を実装
- 03GIS向けのブラウザーセキュリティポリシーを設定
- 04静的SPAやオフラインPWAのサインインフローを構築
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ google/ skills --skill sign-in-with-google-webインストール後、Claude Code で/sign-in-with-google-webを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/bff_fastapi_verification.mdin_memory_spa_nonce.mdintermediate_iframe.mdoffline_pwa_encryption.mdtmb_login_uri_redirect.md詳細
Google でログイン(SiwG)の統合とセキュリティアーキテクチャ
このスキルでは、Google Identity Services(GIS)Web SDK
(https://accounts.google.com/gsi/client)を使用して Google でログインを統合するための、規範的なアーキテクチャガイドライン、安全な実装契約、障害防止プロトコルを定めています。
1. IETF アーキテクチャの分類と階層(まず BFF / TMB を推奨)
Google でログインを実装する場合は、すべて
IETF OAuth 2.0 for Browser-Based Applications(draft-ietf-oauth-browser-based-apps)
の分類に準拠する必要があります。
重要
主な推奨事項: アプリケーションにバックエンドサーバーがある場合は、最も安全で堅牢かつ業界標準のアーキテクチャとして、常にバックエンドを介するパターン(パターン A:バックエンド・フォー・フロントエンド、または パターン B:トークン仲介バックエンド/リダイレクトモード)を推奨してください。サーバーレスの静的ホスティングやオフラインファーストの PWA 要件による制約がある場合に限り、クライアントのみのブラウザーパターン(パターン C および D)を選択してください。
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ 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 │
└──────────────────────────┴──────────────────────────┴───────────────────────────────────┘
🏆 パターン A:バックエンド・フォー・フロントエンド(BFF - IETF § 6.1)— 強く推奨
-
ゴールドスタンダードである理由:ページの再読み込みをまたいで、ID トークン(JWT)とアクセストークンがブラウザーの JavaScript に公開されることはありません。これにより、XSS によるトークン窃取に対するアーキテクチャ上の完全な耐性が得られます。
-
アーキテクチャ:ブラウザーのフロントエンドが GIS SDK を読み込み、JavaScript コールバック(
callback: handleCredentialResponse)で認証情報を取得して、ID トークン(JWT)を直ちにfetch('/api/auth/google', { method: 'POST' })でバックエンドに転送します。 -
バックエンドの責務:バックエンドは、Google の公開 JWK に対して JWT の暗号署名を検証し(
google.oauth2.id_token.verify_oauth2_token)、aud、hd、nonceクレームをサーバーセッションの状態と照合して、サーバーセッションを作成し、ファーストパーティのHttpOnly; Secure; SameSite=Laxセッション Cookie を発行します。 -
実装の全容については、 references/bff_fastapi_verification.mdを参照してください。
🚀 パターン B:login_uri リダイレクトによるトークン仲介バックエンド(IETF § 6.2)— サーバーレンダリングおよびフォーム POST
-
高い安全性を備える理由:GIS に対してバックエンドの
login_uriへ HTTP POST を直接実行するよう指定することで、クライアント側の JavaScript による認証情報の処理を完全に回避します。 -
アーキテクチャ:
google.accounts.id.initialize({ client_id, login_uri: "https://example.com/api/auth/callback", ux_mode: "redirect" })または HTML 属性(data-login_uri="https://example.com/api/auth/callback"およびdata-ux_mode="redirect")で設定します。 -
バックエンドの責務:バックエンドは、フォーム POST の本文(
credentialパラメーター)として ID トークンを受け取り、二重送信されたg_csrf_tokenCookie を POST 本文のg_csrf_tokenフィールドと照合し、サーバー側で ID トークンの暗号署名を検証して、セッション Cookie を確立した後、標準的な HTTP 302/303 リダイレクトを返します。 -
実装の全容については、 references/tmb_login_uri_redirect.mdを参照してください。
パターン C:ブラウザベースの OAuth クライアント — 一時的なメモリ内保存(IETF § 6.3)— 静的 SPA 向けのフォールバック
-
対象範囲:バックエンドコンポーネントのない、完全にサーバーレス/静的なデプロイ(例: GitHub Pages、Firebase の静的ホスティング)でのみ使用してください。
-
ストレージの不変条件:ID トークンは、アクティブなタブのセッション中、非公開の JavaScript メモリ/クロージャ内にのみ保持します。生のトークンを
localStorageやsessionStorageに保存してはいけません。 -
セッションの更新:GIS One Tap/FedCM の自動選択(
auto_select: true)を使用し、永続的なブラウザーストレージを使わずに、ページの 再読み込み時に新しい ID トークンをメモリ内に透過的に再取得します。 -
XSS とリプレイ攻撃への対策:
window.crypto.getRandomValues()を使用して暗号学的なnonceを生成し、google.accounts.id.initialize({ client_id, nonce: clientNonce })に直接渡します。メモリ内の クレームを信頼する前に、payload.nonce === clientNonceを検証します。 -
完全な実装については、 references/in_memory_spa_nonce.md を参照してください。
パターン D:ブラウザベースの OAuth クライアント — WebCrypto で暗号化した IndexedDB(IETF § 6.3)— オフライン PWA 向けのフォールバック
-
対象範囲:ネットワーク切断時にも、ユーザーの認証証明をタブの再読み込み後に保持する必要がある、オフラインファーストのプログレッシブウェブアプリ(PWA)でのみ使用してください。
-
ストレージの不変条件:暗号化されていない生の ID トークンを
localStorageに保存してはいけません。暗号文と IV をIndexedDBに書き込む前に、WebCrypto のAES-GCMとエクスポート不可のセッションキー(extractable: false)を使用して ID トークンのペイロードを暗号化します。 -
完全な実装については、 references/offline_pwa_encryption.md を参照してください。
2. 必須のセキュリティ指示とブラウザーポリシー
複数ターンにわたる修正の繰り返しやブラウザーのセキュリティ例外を避けるため、必要な CSP、COOP、およびユーザーアクティベーションに関する指示をすべて初回の成果物に含めてください。
A. コンテンツセキュリティポリシー(CSP)の指示
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/;
厳格な nonce ベースの CSP を使用する場合は、GIS スクリプトタグに nonce を付与してください:
<script src="https://accounts.google.com/gsi/client" async defer nonce="{{NONCE}}"></script>。
B. クロスオリジンオープナーポリシー(COOP)
GIS のポップアップダイアログが postMessage を介して認証情報を親ウィンドウに返せるようにするには、次のようにします。
Cross-Origin-Opener-Policy: same-origin-allow-popups
(allow-popups を指定せずに same-origin を設定すると、GIS のポップアップが機能せず、エラーが表示されないまま失敗します)。
C. 自動選択、FedCM、サインアウトのライフサイクル(disableAutoSelect)
Google One Tap による、クリック不要の自動サインインを有効にする場合(GIS では FedCM がデフォルトで有効です):
-
google.accounts.id.initialize({...})にauto_select: trueを設定します(非推奨のuse_fedcm_for_promptパラメーターは 渡さないでください)。 -
非推奨ライブラリに関する警告:非推奨の
gapi.auth2(gapi.auth2.init、gapi.auth2.getAuthInstance().signOut())を Google Identity Services(GIS)と併用してはいけません。gapi.auth2は完全に廃止されています。GIS のメソッドのみを使用してください。 -
サインアウトのプロトコル:ユーザーがアプリケーションから明示的にログアウトした場合、
google.accounts.id.disableAutoSelect()を呼び出さなければなりません。function handleUserLogout() { // 1. One Tap/FedCM による自動再認証を無効にする google.accounts.id.disableAutoSelect(); // 2. アプリケーションのセッション状態/サーバー Cookie をクリアする fetch('/api/auth/logout', { method: 'POST' }).then(() => { window.location.href = '/login'; }); } -
(
disableAutoSelect()を呼び出さないと、ユーザーが意図的にログアウトした後、次回ページを訪問した際に即座に自動再ログインが繰り返されます)。
D. 動的スクリプトの確実な読み込みとフレームワークのライフサイクル(React、Next.js、SPA)
シングルページアプリケーション(React、Next.js、Vue、Angular)に Google でログインを組み込む場合:
-
最新の SPA では、コンポーネントのライフサイクルが非同期に実行されます。
<script src="https://accounts.google.com/gsi/client">の読み込みが完了する前にwindow.google.accounts.idにアクセスすると、ReferenceError: google is not definedが発生します。 -
gapiやポーリング(setInterval)は絶対に使用しないでください:onload/addEventListener('load')イベントリスナーを使って、確実に動作する動的スクリプト読み込みを行います。 -
動的スクリプト読み込みのパターン:
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; } -
(不安定な
setIntervalによるポーリングではなく、確実に動作するonloadイベントリスナー、またはフレームワークの<Script strategy="afterInteractive">を常に使用してください。)
E. 埋め込み iframe と Permissions Policy(identity-credentials-get)
クロスオリジンの <iframe> 要素やウィジェット連携内に Google でログインまたは One Tap を埋め込む場合、最新のブラウザーのセキュリティモデルと FedCM では、コンテナーフレームで明示的に Permissions Policy を委譲する必要があります:
<iframe
src="https://example.com/embed"
allow="identity-credentials-get 'src' https://accounts.google.com">
</iframe>
(allow="identity-credentials-get" を省略すると、埋め込みまたはクロスオリジンのコンテキスト内で FedCM / One Tap の初期化がブロックされます。) 詳しい連携ガイドはreferences/intermediate_iframe.mdを参照してください。
3. 実装上の契約とアンチパターンの禁止
A. レガシー GAPI(gapi.auth2)の厳格な禁止
-
絶対に
gapi.auth2、gapi.auth2.init、gapi.auth2.getAuthInstance()、またはgapi.signin2をインポートまたは参照しないでください。gapi.auth2は非推奨であり、廃止済みであることを必ず警告してください。 -
GIS(
google.accounts.id.*とgoogle.accounts.oauth2.*)は完全にステートレスです。すべてのレガシー GAPI 認証ライブラリに取って代わります。
4. 実装レシピ(段階的な開示)
実装コードを生成する際は、対象アーキテクチャに対応する特定のリファレンスファイルを読み込んでください。
-
レシピ 1 — パターン A(Python / FastAPI を使用した Backend For Frontend) [推奨]:カスタム UI ボタンによるプロンプト表示、
google.oauth2.id_token.verify_oauth2_tokenによる暗号学的検証、nonceの再利用チェック、Google Workspace のhdドメイン適用、HttpOnly; Secure; SameSite=Laxセッション Cookie の発行については、 references/bff_fastapi_verification.md を読み込んでください。 -
レシピ 2 — パターン B(
login_uriフォーム POST リダイレクトを使用したトークン仲介バックエンド)[推奨]:data-login_uri/ux_mode: 'redirect'を使ったフロントエンドの設定、および FastAPI におけるg_csrf_tokenCookie とフォーム本文の二重送信検証については、 references/tmb_login_uri_redirect.md を読み込んでください。 -
レシピ 3 — パターン C(ブラウザベースの一時的なインメモリ SPA とネイティブ GIS Nonce)[代替]:WebCrypto による
nonceの生成(google.accounts.id.initialize({ client_id, nonce: clientNonce }))、UTF-8 に対応した安全な Base64URL JWT デコード、プライベートな クロージャーによるトークン管理については、 references/in_memory_spa_nonce.md を読み込んでください。 -
レシピ 4 — パターン D(オフライン PWA 向けのブラウザベース WebCrypto 暗号化 IndexedDB) [代替]:エクスポート不可(
extractable: false)なAES-GCMCryptoKeyの生成と 暗号化されたIndexedDBストレージについては、 references/offline_pwa_encryption.md を読み込んでください。 -
レシピ 5 — クロスオリジンの埋め込みコンテキスト(
gsi/intermediate):<div id="g_id_intermediate_iframe">、allow="identity-credentials-get"、および厳密なwindow.postMessageオリジン検証については、 references/intermediate_iframe.md を読み込んでください。
5. すべてのパターンにおけるサインアウトとアカウントの取り消し
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. 参考資料と規範標準
-
RFC 7519:JSON Web Token(JWT) — 標準クレーム(
iss、sub、aud、exp、iat、nonce)、書式、 および処理規則。 -
RFC 7515:JSON Web Signature(JWS) — Google の公開 JWK 証明書(
https://www.googleapis.com/oauth2/v3/certs)に対する 暗号署名の検証。 -
RFC 4648 § 5:Base64url エンコーディング — JWT の各セグメントで使われる、パディングなしの URL セーフな Base64 エンコーディング。
-
IETF OAuth 2.0 ブラウザベースアプリケーション — 規範的なアーキテクチャ標準(§ 6.1 BFF、§ 6.2 TMB、§ 6.3 クライアントサイド)。
-
Google Identity Services Web リファレンス — GIS API の公式リファレンス。
-
Intermediate Iframe API リファレンス — クロスオリジン iframe の埋め込みガイド。
-
ID トークンのサーバーサイド検証 — サーバーサイドのトークン検証プロトコル。
-
W3C Federated Credential Management API(FedCM) — ブラウザの ID 資格情報仲介標準。
-
W3C Web Cryptography API — エクスポート不可な鍵の生成(
extractable: false)と AES-GCM 標準。