Thomas 花了兩小時嘗試 Google Sign-In,最後發現簡單密碼才是正解。完整踩坑紀錄 + AI Agent 的時間都浪費在哪。
Thomas 有一堆部署在 Cloudflare Pages 的靜態網站,有些包含私人資料(稅務報告、訓練計劃)。需要一個簡單的方式阻止隨便的人打開。
最初的想法是:用 Google 帳號登入,只允許 thomastangnz@gmail.com 進入。聽起來很高級,對吧?
最終放棄 Google OAuth,改用 HTML 密碼輸入框 + localStorage 30天記住。簡單、零依賴、零配置、零外部服務。
Google Sign-In 需要一個 OAuth 2.0 Client ID(Web Application 類型)。直覺想法:用 gcloud 一行命令搞定。
AI Agent 嘗試了 6+ 個 REST API endpoint,全部失敗:
| 嘗試的方法 | 結果 |
|---|---|
gcloud iam oauth-clients create --client-type=WEB_CLIENT | WEB_CLIENT 不是合法選項(這命令是給 Workforce Identity 用的) |
oauth2.googleapis.com/v1/projects/.../oauthClients | 404 Not Found |
clientauthconfig.googleapis.com/v1/... | 404 Not Found |
oauthconfig.googleapis.com/v1/... | 404 Not Found |
iap.googleapis.com/v1/projects/.../brands | 400: Project must belong to an organization |
apikeys.googleapis.com/v2/... | 空結果(這是 API Key,不是 OAuth) |
Google 不提供公開 API 建立標準 OAuth 2.0 Client ID。只能用 Google Cloud Console 網頁手動建立,或用桌面自動化(Playwright)操作 Console。
當你發現自己嘗試了第 3 個 API endpoint 還是失敗,應該停下來搜尋「能不能用 API 做這件事」,而不是繼續猜 endpoint。有些 Google 服務就是只有 Console UI。
API 不行,那就用 AI Agent 的桌面自動化功能(Playwright + Chrome Debug Port)操作 Console。結果:
Console UI 操作(只需要點 3-5 下的事)讓人手動做永遠比桌面自動化快。Playwright 適合重複性高、步驟多的操作,不適合一次性的簡單配置。
好不容易建好了 OAuth Client ID,部署了帶 Google Sign-In 的網頁。點擊登入按鈕,看到:
禁止访问:发生了授权错误
The OAuth client was not found.
Error 401: invalid_client
Client ID 明明存在(Console 上能看到),為什麼 Google 說找不到?
GCP 建立 OAuth Consent Screen 時,預設是 Testing 狀態。在這個狀態下:
修法:去 GCP Console → APIs & Services → OAuth consent screen → 點 PUBLISH APP,或者手動加入你的 email 作為 Test User。
console.cloud.google.com有些網站之前用 Cloudflare Access(Zero Trust)保護。即使部署了新的帶密碼的 HTML,用戶打開網址看到的還是 Cloudflare 的登入頁(那個顯示 Google OAuth 錯誤的頁面)。
原因:Cloudflare Access 在 CDN 層攔截請求,優先級高於你的 HTML 內容。你的密碼頁面根本沒機會載入。
如果改用 HTML 密碼保護,就不再需要 Cloudflare Access。必須手動移除。
one.dash.cloudflare.com(Cloudflare Zero Trust Dashboard)Cloudflare Access(Zero Trust)的 API 需要特殊的 API Token 權限。wrangler 預設的 OAuth Token 只有 Pages/Workers/KV/D1 等權限,沒有 Zero Trust 管理權限。所以只能手動操作 Dashboard。
AI Agent 完成了三步(建 OAuth Client → 改 HTML → 部署),回報「全部完成」。但用戶打開網站一試,直接報錯。
原因:AI 沒有在部署後打開網站實際測試登入流程。如果測了,就能當場發現 Consent Screen 的問題。
任何涉及認證/登入的改動,部署後必須實際走一遍完整流程。不是看代碼「應該沒問題」,而是真的打開瀏覽器點一下。
折騰了 Google OAuth 兩小時後,最終方案是最簡單的:一個密碼輸入框。
<!-- 1. CSS - 加在 <style> 裡 -->
#pw-screen {
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background: #0f172a; z-index: 9999;
display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 16px;
font-family: sans-serif;
}
.pw-title { font-size: 1.5rem; font-weight: 700; color: #e2e8f0; }
.pw-sub { color: #94a3b8; font-size: 0.9rem; }
#pw-input {
padding: 12px 20px; border-radius: 10px;
border: 1px solid #334155; background: #1e293b;
color: #e2e8f0; font-size: 1rem; width: 260px;
text-align: center; outline: none;
}
#pw-input:focus { border-color: #60a5fa; }
#pw-btn {
padding: 10px 32px; border-radius: 10px; border: none;
background: #60a5fa; color: #fff; cursor: pointer;
}
#pw-error { display: none; color: #fb7185; font-size: 0.85rem; }
<!-- 2. HTML - 加在 <body> 最前面 -->
<div id="pw-screen">
<div style="font-size:2.5rem">🔒</div>
<div class="pw-title">請輸入密碼</div>
<div class="pw-sub">此頁面受密碼保護</div>
<input type="password" id="pw-input" placeholder="請輸入密碼" />
<button id="pw-btn" onclick="checkPw()">進入 →</button>
<div id="pw-error">密碼錯誤,請重試</div>
</div>
<!-- 3. Script - 加在 </body> 前面 -->
<script>
const PW = '你的密碼';
const PW_KEY = location.hostname + '_pw'; // 每個網站獨立 key
const PW_DAYS = 30;
function isPwOk() {
try {
const d = JSON.parse(localStorage.getItem(PW_KEY) || '{}');
return d.ok && Date.now() < d.exp;
} catch(e) { return false; }
}
function checkPw() {
if (document.getElementById('pw-input').value === PW) {
localStorage.setItem(PW_KEY, JSON.stringify({
ok: 1,
exp: Date.now() + PW_DAYS * 24 * 60 * 60 * 1000
}));
document.getElementById('pw-screen').style.display = 'none';
} else {
document.getElementById('pw-error').style.display = 'block';
document.getElementById('pw-input').value = '';
document.getElementById('pw-input').focus();
}
}
// 頁面載入時自動檢查
if (isPwOk()) {
document.getElementById('pw-screen').style.display = 'none';
}
document.getElementById('pw-input')
.addEventListener('keydown', e => { if (e.key === 'Enter') checkPw(); });
</script>
| 階段 | 花費時間 | 問題 |
|---|---|---|
| 嘗試 6 個 API endpoint 建 OAuth Client | ~40 分鐘 | 應該第 3 次失敗就停下來確認「這東西有沒有 API」 |
| 桌面自動化操作 GCP Console | ~20 分鐘 | 人手 2 分鐘能搞定的事 |
| 部署後沒有測試 | — | 交付了壞的東西,浪費下一輪時間排查 |
| 排查 401 invalid_client 錯誤 | ~15 分鐘 | 如果部署後立刻測試,這 15 分鐘可以省掉 |
| 總計浪費:~75 分鐘(人手做完全程只需 10 分鐘) | ||
| HTML 密碼 | Google Sign-In | Cloudflare Access | |
|---|---|---|---|
| 難度 | 簡單(複製模板) | 中等(需 GCP 配置) | 中等(需 CF 配置) |
| 外部依賴 | 無 | GCP 項目 + Consent Screen | CF Zero Trust |
| 安全性 | 低(密碼在前端) | 高 | 高 |
| 適用場景 | 私人靜態網站 | 需要識別用戶身份 | 企業級保護 |
| 壞掉風險 | 極低 | 高(Consent Screen、API 變更) | 中(Token 權限問題) |
| AI 可自動化 | 完全可以 | 部分需手動 | 部分需手動 |
當你需要識別用戶身份(不只是擋住陌生人)的時候。例如:多用戶系統、不同用戶看到不同內容、記錄誰做了什麼操作。如果只是「不想讓隨便的人看到」,HTML 密碼就夠了。