關於 SSO 登出的那些事:Google、Microsoft、LINE 開發者必讀差異
前情提要
為何大家現在都喜歡採用 SSO?
我最近手上很多案子,都建議客戶不要自己實作帳號密碼登入,而是直接採用SSO登入。
因為,現今資安與用戶體驗的雙重考量,很多專案開發時,都會選擇整合 Google、Microsoft、LINE 這類大廠的 SSO(Single Sign-On,單一登入)機制,來取代自己儲存帳號密碼,如此可以降低很多資安風險,在面對資安稽核的時候,也省了一些什麼資料庫帳號密碼加密、金鑰保存的一堆麻煩。
而採用SSO對用戶也有一個好處,就是用戶不再需要記得很多組密碼,可以輕易實現 「一個帳號,多處通行」。用戶在某個服務登入一次,其他整合同一身份平台的 網站/應用程式 就能直接使用,不必每次重新輸入帳密。對用戶來說方便,對開發者來說省事,對資安來說統一控管理論上也比較更安全。
但,不是每個 SSO 都能「好好登出」
某次,被客戶問到了一個問題。
客戶的用戶,使用瀏覽器登入我們的系統,但該瀏覽器會記得用戶的SSO session,因此當用戶關閉瀏覽器後,重新開啟瀏覽器登入系統時,看似需要登入,但發現即便導引到了SSO的登入畫面,卻無須輸入帳密,隨即可以登入!?
其實,SSO單一登入機制 by design 就是這樣設計的,這本來就是SSO的便利性和好處。然而,客戶卻有個疑問,如何強制讓用戶一定要用戶重新輸入帳密呢?
事實上,還真的不是每個 SSO 都能「登出」
雖然許多人都有用過 SSO,但可能很多人不知道:不是每一個 SSO 都有支援「全域登出」的 API 或 URL。
事實上,很多整合 SSO 的「登出」功能,本質上只是在下一次登入時強迫重新驗證,並不是真的清空 IdP(身份提供者)的全域 Session。
更有趣的是:這個所謂的「重新驗證」也不一定會要求用戶重新輸入密碼。
有的 SSO 可以透過特定的參數在登入時直接強迫用戶輸入帳密(無視現有 Session),有的則只能「盡力要求」。最後要不要真的打密碼,還得看 SSO Provider 如何實作安全政策(例如MFA、零信任)。
就拿我在專案中最常使用的 MS, Google, LINE 三種 SSO Provider 來說,對於「登出」與「重新登入」的實作方式都不同。
Microsoft — 最直白的強制重登
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
?client_id=...
&response_type=code
&redirect_uri=...
&scope=openid profile email
&state=...
&prompt=login
prompt=login
會直接要求重新輸入憑證,SSO 再見。
Google — 溫和又含蓄的提醒
https://accounts.google.com/o/oauth2/v2/auth
?client_id=...
&response_type=code
&redirect_uri=...
&scope=openid email profile
&state=...
&max_age=0
&prompt=select_account
max_age=0
:要求重新驗證prompt=select_account
:至少會出現帳號選擇器,但不一定要密碼- Google 不支援
prompt=login
LINE — 有點任性的選擇性重登
https://access.line.me/oauth2/v2.1/authorize
?client_id=...
&response_type=code
&redirect_uri=...
&scope=openid profile
&state=...
&prompt=login
&max_age=0
&disable_auto_login=true
prompt=login
:要求顯示登入畫面max_age=0
:觸發重新驗證檢查disable_auto_login=true
:避免 LINE 自動帶你進去- 但如果 LINE App/Web session 還在,可能依舊秒過
小小總結
- 如果你的場景一定要使用者重新輸入帳密,Microsoft 是最好控制的。
- Google/LINE 只能盡量逼近結果,但無法百分百保證,需要配合清除 IdP cookie 或瀏覽器的無痕模式來達成。(所以,如果用戶要保證你的帳號不殘留,要求用戶使用無痕視窗是最安全的)
- 登出策略要根據安全需求、用戶體驗與 IdP 限制來決定,不要假設「重新登入 == 一定會要求用戶重新輸入」。
關於登入策略
假設你的應用程式採用了 SSO 登入,大部分應用程式實作的登出功能,其實只是清除應用程式本身的 token/session,但不影響 IdP 的 SSO 狀態。(這也是用戶重新開啟瀏覽器,進行登入時無須輸入帳密的原因)
如果要清除IdP 的瀏覽器 Session,可使用 /logout(Google/Microsoft 可做到,但 LINE 沒有),不然就是用戶必須手動清除瀏覽器 cookies。而如果要 強制重新驗證,則可以透過 redirect url 參數(如 prompt=login
、max_age
)讓用戶在下一次登入SSO十,一定要經過互動驗證(但並不代表 100%會重新輸入密碼)。
開發時,你必須確認你的用戶所要的登出,究竟是哪一種登出,並且跟用戶做好說明。免得用戶「以為自己已經登出」但其實重開瀏覽器後,還是秒登入。
提醒 👉 別假設「重新登入 == 打密碼」
Google / LINE 可能直接讓用戶選帳號或用 Passkey/Face ID 通過,完全沒有打密碼的機會。如果你的需求是高資安情境(如銀行交易、重大設定變更),請結合清除全域 cookie 或乾脆引導用戶使用無痕模式。
另外,「登出」和「切換帳號」是不同的邏輯,很多時候,使用者的「登出」,其實是想換另一個帳號登入。對 Google / LINE 來說,prompt=select_account
是比較柔和的做法,可以讓用戶切帳號而不完全破壞 SSO 登入狀態。(但要注意這等於同一個瀏覽器登入了多個帳號,絕對不適合讓用戶在公用電腦使用)
以上,是SSO在登出上的一些實作策略,希望對開發應用程式的大家有幫助。
底下是展示 repo:
https://github.com/isdaviddong/sso-relogin-demo
留言