本章幫讀者做兩個決定:登入的身分自己管還是交給外部的身分提供者,以及自己管的話拿什麼驗證使用者。

它在 7.28 密碼學原語選型7.29 API 認證的信任邊界分層7.30 使用者密碼儲存 的上游——那三章各自處理已經決定要自己做之後的問題,而這一章決定要不要走進去。

本章涵蓋與不涵蓋

本章聚焦身分從哪裡來、以及驗證用什麼材料這兩個決定。登入節奏、第二因子與權限分級屬 7.2 身分與授權邊界——終端使用者那一側在該章的「終端使用者的登入節奏」一節,員工與高權限工具在其餘各節。憑證在請求中怎麼帶、狀態放伺服器還是放 token 是接在這兩個決定之後的另一條軸。狀態放哪裡的取捨(sticky session、外部 session store、無狀態 token,含撤銷成本)見 Session 處理;憑證怎麼帶(cookie 自動附上與請求標頭明確附上各自的攻擊面)見 7.36 憑證在請求中怎麼帶。機器對機器的身分不在本章範圍,那條路徑的入口是 7.29;人類使用者持客戶端憑證登入(企業與政府的智慧卡)也不在本章的形態裡,它與硬體金鑰同屬一條軸、看實體持有而非猜測成本,判讀見 7.39 使用者持有型憑證

判讀軸:材料落在哪裡

本章說的「材料」指驗證身分時拿去比對的那一段值:密碼、私鑰、寄到信箱的一次性碼都算。各種做法的實際差別是可離線猜測的材料最後落在哪裡、由誰保護——它不會因為主路徑換了機制就消失,要看它被移到哪裡,或者被什麼代價換掉了。

「可離線猜測」問兩件事。第一,這段材料是不是人選出來、人記得住的:是就是低熵。第二,攻擊者拿到落地的那一份之後,驗證猜測還需不需要再打這個服務:不需要就是離線,而離線意味著沒有速率限制、沒有帳號鎖定、也沒有任何告警會響。兩項都成立的那一段就是實際的攻擊面,它適用的是 7.30 的那套判讀,不論主路徑用了什麼。

這條軸判的是「拿到材料之後能不能大量猜」這一類成本。硬體金鑰與生物辨識的成本結構不同——要偷到實體、要騙過感測器——那一條軸看的是憑證離不離得開它的載體,判讀走 7.39 使用者持有型憑證。該章同時處理一個容易混淆的分類:生物辨識在那條軸上是載體的鎖而非載體本身。

兩個先後的決定

把選型拆成兩個決定,因為它們正交——混在一起會讓「委派給一個用 passkey 的身分提供者」「自建帳號但用 passkey」這類常見組態找不到位置。

決定一:身分從哪裡來。 自建(自己管帳號)、委派(federated identity,把登入整個交給外部的身分提供者;與 7.33 的「委任」是不同的事,那裡指一個系統代表某個特定的人去做事)、或不建立持久身分(一次性登入連結、裝置綁定憑證、單純不要帳號)。這一項由使用者群體決定,見下方「使用者的身分從哪裡來」一節。

決定二:驗證用什麼材料。 共享秘密(密碼)、金鑰對(passkey)、或一次性的值(寄到信箱或簡訊的驗證碼)。這一項只有走自建那一邊時才由自己決定,判準是三問:

  • 使用者多久來一次。低頻到記不住密碼的服務(一年報稅一次、偶爾查帳單),一次性的值省掉整套密碼治理,而使用者本來每次也都要重設。
  • 裝置是不是穩定屬於同一個人。是的話 passkey 可行;共用電腦、公用終端、或使用者會在陌生裝置登入的服務,passkey 的體驗與回復成本都會變差。
  • 有沒有人負責設計帳號回復。passkey 的安全上限由回復路徑決定,沒有人接這件事時,密碼加第二因子是更誠實的選擇——它的弱點已知、也有現成的處置。

委派時第二個決定由對方做,而這件事本身是委派的第四個依賴:登入強度的上限被對方封頂。對方只支援密碼時,這邊就算想要 passkey 也拿不到;對方的密碼政策鬆,這邊的實際強度就是那個鬆的水準。這條依賴是本章的判讀軸套在委派上的直接結論——材料在對方那邊,保護它的規則也在對方那邊。

多數服務最後是組合:主路徑走委派或 passkey、fallback 走自建加密碼。組合的判讀不變,逐條路徑問同一個問題,而答案由最弱的那一條決定

常見的四種組合把材料移到哪裡

兩個決定的組合有好幾種,以下展開最常見的四種。自建加一次性的值與下方「不建立持久身分」的一次性登入連結共用同一段路徑、材料落點相同,差別只在有沒有留下帳號,因此不另外展開。

自建加密碼把它放在前門,自己承擔全部:參數選型與老化(7.30)、登入節奏與異常判讀(7.2 終端使用者的登入節奏)、以及外洩密碼被拿來試登入這一格(見 credential stuffing)。

自建加 passkey 把材料換成裝置持有的金鑰對,服務端存的是公鑰,公鑰外洩不構成可還原的風險。它同時擋掉 credential stuffing 與釣魚——前者沒有可重用的秘密,後者的簽章由瀏覽器綁在當下的網域上,釣魚站的網域不同就產不出可用的簽章。材料移到兩個地方,而它們的安全水準不同:

  • 憑證隨平台帳號同步時,材料實際上移到那個平台帳號,而它自己多半仍由一組密碼加第二因子守著。這是本章判讀軸最直接的例證——換了機制,材料換了住址而沒有消失。
  • 憑證綁在單一裝置時,沒有同步副本,跨裝置登入靠原裝置掃碼完成單次驗證、掃完那台仍然沒有憑證。這一種的材料真的不在任何可猜測的位置上,代價是換裝置之後憑證沒跟過去,路徑接回帳號回復。

同一個服務上兩種形態會同時存在,取決於使用者的作業系統與瀏覽器組合,而使用者分不出自己手上是哪一種。這一格因此要先設計帳號回復——回復路徑若含可猜測的材料,材料就落在那裡;若回復要求持有第二支已註冊裝置或走人工核身,這條路上就沒有可離線猜測的材料,代價換成不可回復的帳號與人工核身的人力。回復的安全水準要在主路徑上線前決定,決定之後可以先由人工承擔、有量體再自動化。

委派身分換來的是不必碰密碼儲存,付出四樣依賴。前三樣的落點不同:

  • 身分提供者的可用性直接等於自己的登入可用性——對方的控制面故障時,這邊沒有任何一條路能讓使用者進來。形態與恢復優先序見模組案例 7.C3 Azure AD 身分控制面事件
  • 帳號的生命週期由對方決定——對方停用帳號時這邊不會收到任何事件,除非另接一條反向通道。這條通道有既成標準:SCIM 管帳號的開通與停用、OIDC 的 back-channel logout 管單一 session、Shared Signals 的帳號停用與會話撤銷事件管推送。落差在對方支不支援,所以它是對接契約的一項,而不是自己這邊寫得完的東西。
  • 使用者離開那個來源時(換公司、平台停用帳號)這邊的資料歸屬要另外設計——這是產品決定而非技術決定,三個要在導入當下定案的問題(保留多久、歸誰、匯出給誰)見 7.38 外部身分與本地紀錄

第四樣是上一節說的登入強度上限。供應商那一端出事時的內部收斂責任走 7.2 供應商身分鏈傳導;跨組織的信任建立與 token 範圍走 7.10 Workload Identity 與聯邦信任邊界,注意那一章的主體是機器對機器那一側。

不建立持久身分適用於使用頻率低、或使用者與裝置一對一的服務。一次性登入連結把材料移到使用者的信箱,於是這個服務的實際安全水準等於那個信箱帳號的安全水準,而它多半仍由密碼守著;送達延遲也會直接變成登入延遲。裝置綁定的長效憑證見 7.2 單人裝置認證模型。這一格還有一項與資安治理直接相關的代價:沒有持久身分時行為無法歸屬到人,事後調查與合規稽核因此沒有依據——稽核欄位要記什麼、保存多久才夠回查,見 7.7 稽核追蹤與責任邊界

使用者的身分從哪裡來

決定一由這一項決定,而它是產品事實而非技術選擇。

使用者集中在單一組織時委派最乾淨:一個身分提供者、一套帳號生命週期、離職即失效。企業內部系統與只服務單一組織的 B2B 多半落在這裡,而且刻意不留密碼 fallback——留了就等於在對方的紀律之外開一道門。

消費端分散時,委派會變成「支援哪幾家」,而每多一家就多一組設定、一組錯誤處理與一組帳號合併問題:同一個人用不同來源登入兩次,這邊要判斷是不是同一個人,而那個判斷沒有可靠的依據(信箱相同不代表同一人、也不保證那個信箱沒換過主)。帳號合併的設計見 7.38 外部身分與本地紀錄,預設做法是不自動合併、改成讓使用者在已登入的狀態下主動綁定第二個來源。這一格的結論是需要一條不依賴任何單一來源的路徑,而不是自建躲不掉——那條路徑用什麼材料是決定二,密碼、passkey 與一次性連結都在選項裡。

B2B 多租戶是另一種形態:每個客戶帶自己的身分提供者,於是這不再是選型而是要做成可設定的能力——每租戶一組身分提供者設定、一組網域對應規則、以及新客戶自助接上的流程。這項能力的設計見 7.40 B2B 多租戶的身分接入,它的判讀軸是租戶歸屬由誰主張、由誰驗證。

判別自己落在哪一格,問的是「這個服務的使用者,在來到這裡之前已經有哪個帳號」。答案是同一個時委派可行;答案是好幾個或沒有時,要準備那條不依賴單一來源的路徑。

委派優先於自建的預設,以及它的代價

使用者本來就集中在某個來源時,委派通常是對的選擇——不必碰密碼儲存、帳號生命週期跟著對方走、離職即失效這三項是實打實的省。

這個預設有一個值得認真對待的反面:密碼儲存在今天接近已解決的工程問題(一個函式庫、一組建議參數、一條升級路徑,7.30 一章就寫完了),而委派引入的是不可控的依賴。選它要付三樣——退出成本近乎不可逆(換身分提供者等於全體使用者重新註冊,憑證無法遷移)、安全上限被對方封頂對方故障時完全沒有替代路徑,而自建至少故障在自己手上。長生命週期的產品要把這三項算進去再決定。

判讀流程

  1. 先確認使用者在來到這個服務之前已經有哪個帳號,答案決定委派可不可行。可行之後再過一次退出成本、安全上限、故障替代這三問——見上一節,可行與該選是兩件事。
  2. 再列出所有進得來的路徑,而回復路徑與 fallback 都算——這一步最常只列到主路徑就停。系統還沒實作時把規劃中的每一條寫下來即可,重點是別漏掉「忘記了/換裝置/找客服」這三種情況各自會走哪裡。系統已經在跑時用反查:從 session 的建立點出發,枚舉所有能發出 session 或 token 的端點,再補三類程式碼裡看不到的——舊版行動應用留下的獨立登入端點、從別的系統匯入的舊帳號、以及客服能不能替使用者改綁定信箱或手動核身。最後一類最常被漏掉,也最常被利用——那條路徑的授權要怎麼設計(誰能發動、要不要理由與時窗、紀錄怎麼歸屬)見 7.2 代理操作的授權邊界
  3. 對每一條路徑問「這一段有沒有可離線猜測的材料」,用上方的兩問判定。判成「沒有」時要寫出材料被移到哪裡——哪個平台帳號、哪支裝置、哪一條回復路徑——寫不出來代表這條路徑還沒判完,因為材料不會消失。判成「有」的話那一段要做三件事:用刻意放慢的雜湊存(不是一般用途的雜湊)、參數取公開建議值當下限再依自己的硬體往上加、留一條參數升級路徑因為那組值每年都在變弱。完整的定法與升級走 7.30 使用者密碼儲存
  4. 最後把選定的方式路由到對應的下游。自建加密碼走 7.30 使用者密碼儲存7.2 終端使用者的登入節奏。委派分兩條:對方出事之後自己這邊的收斂走 7.2 供應商身分鏈傳導,而帳號狀態不同步(對方停用了、這邊不知道)走 7.38 外部身分與本地紀錄,它的反向通道那一節列出對接當下要問對方的事。passkey 的載體形態、註冊起點與導入節奏走 7.39 使用者持有型憑證,它的判準是先把回復路徑設計完再開主路徑。

這個決定失敗時長什麼樣

幾種形態裡委派身分的後果最不直觀,因為它的成本以缺席的形式出現——沒有事件、沒有告警、沒有任何一項工作變多——而不是以工作量的形式出現。其餘幾種不另寫的理由是後果已經直觀:自建的後果欄字面就是密碼被猜到,passkey 的不直觀之處(同一個服務上兩種形態並存、使用者分不出自己手上是哪一種)在上方那一段已經寫成可想像的形態,不建立持久身分的代價是門鎖交給別的系統、讀者從那一句就推得出後果。

它的失敗長這樣:團隊把登入交給客戶的身分提供者,帳號生命週期因此不必自己管——這正是當初選它的理由。某位客戶的員工離職,對方在自己的目錄裡停用了帳號,而這邊沒有收到任何事件:委派的方向是使用者拿著對方的憑證過來,對方沒有義務主動通知這邊帳號狀態變了。那個人手上還沒過期的會話照常可用,而當初為「沒有那個來源帳號的使用者」留的那條密碼 fallback,對他一樣開著。沒有人發現的原因是這邊的後台顯示那個帳號一切正常——本地狀態是上次登入時寫進去的,之後沒有任何東西會去更新它。補起來要先向對方要一條帳號狀態的推送,而那是導入當初沒有談進契約的東西,事後補等於重開一次對接。

常見風險邊界

  • 列得出主要登入路徑、列不出全部的回復路徑時,代表安全上限還沒有被評估過——回復路徑決定的是實際上限而非例外處理。
  • 委派身分而沒有反向的帳號狀態同步時,對方停用帳號在這邊不產生任何事件,既有會話與 fallback 都還開著。這一條要在導入當下談進契約,事後補要重開對接。
  • 支援多個身分來源而沒有定義同一個人的判別依據時,帳號會分裂,而合併帳號牽涉的是資料歸屬而非登入流程。
  • 主路徑用了 passkey 或委派,fallback 卻沿用最早那套密碼設定時,實際的安全水準由 fallback 決定,而它多半是最久沒有被檢視的那一條。

下一步路由