◆ wport | pm_39

pm_39 第三方登入 — 6 個 UI 狀態對齊

第三方登入 2.0(Apple 等)

來源 doc/feature/pm_39/pm_39-design-handoff.md

pm_39 第三方登入 — 6 個 UI 狀態對齊

spec review 後發現,Apple 登入的後端行為 90% 跟 Google 相同,但有 6 個畫面狀態 v1 既有從來沒設計過——其中 3 個是 Apple 獨有,另 3 個是 Google 也會用到(既有畫面可一併補齊)。

設計工時請與 Designer 評估後決定。PM 已決策(見下節)


PM 決策(2026-05-27)

結論:6 項 UI 狀態全部要做(PRD 行為落地),但不另開設計工單、不產 Storybook、不各做一份 Figma。 FE 依 PRD §6(SEC-4 / SEC-5 / SEC-6)與 §10.5 錯誤碼 → UI 對應表 直接實作,沿用 wport 既有 modal / toast / banner / disabled button 元件。

Single source of truthdoc/feature/pm_39/third-party-auth-mockup.md §6 + §10.5(若 handoff 與 PRD 衝突,以 PRD 為準)。

逐項交付方式

#項目要不要畫圖FE 怎麼做
step-up 彈窗解綁/加綁 API 觸發;沿用 confirm modal(對齊 SEC-6 風格)。§10.5 STEP_UP_REQUIRED:標題 +「重做 OAuth」/「輸入密碼」二選一;無密碼用戶僅顯示 OAuth 路徑
解綁 disabled + tooltipcan_unlink=false 事前 disable + hover tooltip(SEC-4 文案);不做 prod 現行「點了才 400 報錯」
Apple relay 失效 banner帳號管理頁頂部 warning banner;文案依 PRD §10.4 / BR-031
客服恢復全頁v1 复用既有全頁引導/錯誤頁模板 + PM 確認文案;低頻 edge case,不單獨排設計
外部撤銷依 PRD §10.5 做 ToastBINDING_REVOKED_BY_PROVIDER),不做 handoff 原述之全頁
auto-merge Toast依 SEC-5:登入成功 + 觸發合併時顯示,5 秒自動消失,可手動關閉

解綁流程順序(FE 鎖定)

SEC-4 點「解除綁定」
  → ① step-up 再驗證(BR-028)
  → SEC-6 確認對話框
  → 解綁 API

給 RD / FE 的說明

  • 本文件為 RD spec review 的缺口盤點,標出 PRD 有寫但 §16 設計交付未列全的 UI 狀態;不代表必須等設計師出圖才能開工
  • 6 項皆為既有元件上的狀態變體(非新 login 版型);業界有固定 pattern(step-up re-auth、last-method disabled、merge notification 等)。
  • §16 sync-fix #7「Figma 補 SEC-4/5/6」:v1 不另排;FE 直接依 PRD 實作。若 step-up 按鈕排列需對齊,FE 對齊 SEC-6 modal 即可,不必等 Figma。

仍待 PM 確認的文案(不 block FE 開工)

  • ③ banner 文案:以 PRD §10.4 為準(若與本文件 §③ 場景描述不同,實作前 PM 統一一版)
  • ④ 恢復後引導頁文案:v1 模板 + 下列方向——「帳號已恢復,請設定備援登入方式」

6 項出處彙總(PRD 明文 vs spec 自加)

#項目PRD 出處spec 自加部分
step-up 彈窗明文 — line 70 / 175–177(BR-028 解綁必須擇一通過:重做 OAuth 或重輸密碼)僅 UI 細節(版面 / 按鈕排列 / 文案)
解綁按鈕 disabled + tooltip明文 — line 387(§10.4 SEC-4)+ line 437(HINT-GET-1 可解綁 flag),含 disabled 行為與 tooltip 文案無,完整依 PRD 落地
Apple relay 失效 banner明文 — line 218(BR-031)+ line 295(資料實體),含 nudge 觸發時機與文案僅 UI 細節(樣式 / 顏色 / 位置)
客服恢復全頁明文 — line 220–221(BR-031)+ §12.5 SOP僅 UI 細節(全頁版面 / 引導動作呈現方式)
外部撤銷全頁部分 — line 220–221 提及行為「帳號保留 + 可用其他方式取回」「全頁引導 UI」屬 spec 自加;可改用通用錯誤頁
auto-merge Toast明文 — line 100(S2 場景)+ line 120(BR-018),Toast 雙通道明寫僅 UI 細節(樣式 / 文案 / 消失時長)

摘要:6 項中 5 項是 PRD 明文要求(含 ② 連 disabled 行為與 tooltip 文案都明寫),1 項(⑤)為 PRD 提及行為、UI 細節由 spec 補。所有項目的「設計畫面」屬於本來就缺少的 UI 設計工作,並非 spec 額外加碼。


① step-up「再驗證身份」彈窗

Apple / Google 都會用,既有 Google 沒這個東西

出處(PRD 明文要求)

  • PRD line 70(§4.1 功能定位):「解綁、新增綁定的 step-up authentication(重做 OAuth 或重輸 email+password,見 BR-028)」
  • PRD line 175–177(BR-028 詳述):「解綁、新增綁定屬於 sensitive action,除『當前 session 未過期』外,必須額外通過 step-up authentication」 + 「解綁:必須擇一通過 — (a) 重做該 provider 的 OAuth 流程;(b) 重輸 email + password」
  • 結論:行為與兩種驗證方法是 PRD 強制;具體彈窗版面 / 文案 / 兩按鈕排列屬 UI 細節,由設計師補圖

場景

阿明早上用 email 密碼登入 wport,下午想在「帳號管理」解除 Google 綁定,他點 [解除綁定 Google]。

用戶會看到

跳出彈窗「為了你的帳號安全,請再次驗證身份」+ 兩個按鈕:

  • 「用 Google 重新驗證」(會跳 Google OAuth popup)
  • 「輸入密碼」(會彈密碼輸入框)

完成驗證後才執行真正的解綁。

為什麼新加

BR-028 規定所有解綁動作(敏感操作)必須再驗證一次身份,不能光憑 JWT。Apple 跟 Google 都會經過這個彈窗。

如果沒設計師畫

FE 只能用瀏覽器原生 window.confirm() 或預設 modal 處理,會偏離 wport 品牌視覺一致性。

設計需求

  • 彈窗版面:標題 / 說明文字 / 兩個方法按鈕的排列
  • 沒設密碼的用戶(只能用「重做 OAuth」)的退化版
  • 等待狀態 / 錯誤狀態(密碼錯、Apple OAuth 被取消等)

② 解綁按鈕 disabled 狀態 + tooltip

Apple / Google 都會用;本次可改善既有 Google「點下去後才知道不能解綁」的事後提示流程

出處(PRD 明文要求)

  • PRD line 387(§10.4 SEC-4):「若僅綁定 1 種 provider 且未設 email+password → 『解除綁定』按鈕應 disabled 並 hover 顯示 “請先新增其他登入方式”」← 包含 disabled 行為與 tooltip 文案都明寫
  • PRD line 437(HINT-GET-1):「可解綁 flag:後端可預先計算『此筆是否為唯一登入方式』,前端據此決定按鈕狀態(避免 FE 重新算 BR-025)」← 對應 spec 新增的 can_unlink 欄位
  • 結論:disabled + hover 文案是 PRD 明文要求;本次完整依 PRD §10.4 SEC-4 落地

既有 prod 行為佐證

實測 prod POST /v2/api/auth/unbind-google 在「只綁 Google + 未設密碼」用戶按下解除綁定時的回應:

{"message":"解除綁定前需先設定密碼","error":"BadRequest","statusCode":400}

訊息字面引導用戶「去設密碼」,但實際解套方式還包括「加綁其他 provider」。本次 spec 將對應的 i18n path 換成 error.oauth.last_login_method 表達更精確的條件;同時依 PRD §10.4 SEC-4 把按鈕改為 disabled + tooltip,從事後提示升級為事前防呆。

場景

阿明只綁了 Google、沒設密碼,他去帳號管理頁看到 [解除綁定 Google] 按鈕。

用戶會看到

新版:按鈕 grey out 不能點,hover 上去 tooltip 寫:「這是你唯一的登入方式,請先設定密碼或綁定其他登入方式」+ 旁邊有 [前往設定密碼] / [綁定其他] 的引導連結。

既有:按鈕可點,點下去後才跳錯誤訊息「解除綁定前需先設定密碼」(訊息文案不夠精確——實際解套方式還包括「綁定其他 provider」,並非只能設密碼)。

為什麼新加

spec 後端新增 can_unlink 欄位,FE 可以事前知道能不能解綁,按鈕直接 disable 比讓用戶點了才報錯好。

如果沒設計師畫

FE 維持「點下去後才報錯」的事後提示流程,後端新增的 can_unlink 欄位無從發揮;錯誤訊息文案也維持「請設定密碼」這個與實際解套方式不完全一致的版本。

設計需求

  • disabled 樣式(顏色、cursor)
  • tooltip 文案 + 樣式
  • 引導 CTA(設密碼 / 加綁定)的位置與樣式

③ Apple Hide My Email relay 失效 banner

Apple 獨有

出處(PRD 明文要求)

  • PRD line 218(BR-031 event 表):「email-disabled 用戶在 Apple 端關閉 Hide My Email 轉信 | 標記該 Apple binding『relay 失效』flag;下次用戶登入時顯示 nudge「請至設定頁更新可收信 email」;不改動 binding 本身」← 包含 nudge 觸發時機與文案
  • PRD line 295(資料實體):定義 Apple Relay Email Status entity,狀態 active / disabled 由 S2S event 驅動
  • 結論:nudge 行為與基本文案是 PRD 明文要求;banner 樣式 / 顏色 / 位置由設計師補圖

場景

小美用 Apple 註冊 wport 時選了「隱藏我的 Email」,Apple 給 wport 一個 relay 信箱 xyz123@privaterelay.appleid.com。一年後小美在 Apple 設定關掉了這個 relay。Apple 推 webhook 給 wport,wport 立刻更新狀態。下次小美登入 wport,進帳號管理頁。

用戶會看到

頁面上方 banner:⚠️「您的 Apple Hide My Email 已停用,wport 將無法寄通知信給您。請設定備用 email 或重新啟用 relay」+ [前往設定] CTA。

為什麼新加

Apple 用戶用 relay 註冊的話,他的 wport users.email 是 relay 信箱。Apple 端關掉 relay → wport 寄信全部寄不到(進 Apple 黑洞)。我們需要主動告知用戶。

Google 為什麼沒這問題

Google 一律給真實 email,沒 relay 機制。

如果沒設計師畫

用戶不會知道 wport 寄信失敗,重要通知(履歷被瀏覽、應徵狀態變更等)會持續漏接,後續可能轉成「為什麼沒收到通知」的客服詢問。

設計需求

  • Banner 樣式(warning level、是否可關閉)
  • 文案
  • CTA 連去哪(設備用 email 的入口設計也需要 — 這可能是另一個 follow-up 設計)

④ 「帳號需客服處理」全頁通知

Apple 獨有的邊角情境

出處(PRD 明文要求)

  • PRD line 220–221(BR-031 event 表):
    • consent-revoked:「若 Apple 是該用戶唯一登入方式 → 改為標記帳號『需客服恢復』並寄通知信(見 §12.5)」
    • account-delete:「若 Apple 為唯一登入方式 → 進入『需客服恢復』狀態」
  • PRD §12.5:客服恢復 SOP(含工單流程、雙人複核、客服可執行的恢復動作)
  • 結論:「需客服恢復」狀態 + 通知信是 PRD 明文要求;全頁版面 / 引導動作呈現方式由設計師補圖

場景

阿志只用 Apple 註冊 wport(沒設密碼、沒綁 Google)。半年後他刪除 Apple ID 帳號。Apple 推 webhook 給 wport → wport 把他的 Apple binding 刪掉、發現他沒其他登入方式。

阿志過幾天想登入 wport 找他的履歷,點「用 Apple 登入」→ Apple 端已沒這帳號 → 失敗。試「忘記密碼」→ wport 寄重設信給已失效的 Apple relay → 收不到。完全進不去。

他求助客服,客服協助他綁定新 email/密碼後,他下次能登入 wport,第一次登入就會看到這個全頁

用戶會看到

全頁「您的帳號之前因 Apple ID 變更需客服恢復,已恢復完成。請設定新的登入方式以避免未來重複此情況」+ 引導設密碼 + 綁定其他 provider。

為什麼新加

PRD §12.5 客服恢復 SOP 採「不主動刪除孤兒帳號」策略(避免用戶誤刪 Apple ID 即連帶失去整個 wport 帳號),但相對要有明確的狀態告知與引導。

Google 為什麼沒有

Google 不會主動推「帳號已刪除」webhook 給我們(沒對應的 GDPR 通知機制)。

如果沒設計師畫

用戶恢復後若沒收到任何引導,可能不知道該主動設定備援登入方式,類似情境再次發生時客服仍需處理同類工單。

設計需求

  • 全頁版面
  • 文案(解釋發生什麼 + 引導動作,不能太技術)
  • 引導 CTA 設計

⑤ 「綁定已被外部撤銷」全頁

PM 決策:v1 依 PRD §10.5 做 ToastBINDING_REVOKED_BY_PROVIDER),不做下方原述之全頁。以下保留 RD handoff 背景說明。

Apple 獨有(技術上 Google 也可能但實務罕見)

出處(PRD 提及行為、UI 細節由 spec 補)

  • PRD line 220(BR-031 consent-revoked event):「等同 ACT-8 解綁 Apple 路徑(含 BR-029 二層傳播)」+「wport 帳號保留(用戶可用其他登入方式取回)
  • PRD line 221(BR-031 account-delete event):同上「wport 帳號保留」
  • 結論:PRD 明寫「帳號保留 + 用戶可用其他方式取回」的行為要求,但**「用戶下次登入時看到什麼樣的 UI 引導」由 spec 自加全頁設計**(PRD 未明指 layout)。若不做全頁,FE 仍可用通用錯誤頁,但體驗較弱

場景

小華同時用 Google + Apple 都綁定 wport。某天他在 Apple 設定點「停止使用 Apple ID」對 wport。Apple 推 webhook 給 wport → wport 立刻刪 Apple binding。

小華下次用 Apple 登入 wport → 失敗 BINDING_REVOKED_BY_PROVIDER 404

用戶會看到

全頁「您的 Apple 帳號已撤銷對 wport 的授權,無法用 Apple 登入。您可以改用 Google 或密碼登入」+ [用 Google 登入] / [使用密碼登入] CTA。

為什麼新加

Apple 用戶可以在 Apple 設定一鍵撤銷對 wport 授權,UX 設計就是要讓用戶容易做,所以發生率高。

Google 為什麼罕見

Google 也有撤銷介面但藏比較深,且沒主動推 webhook(要 wport 主動偵測,spec 沒做)。

跟 ④ 的差別

還有其他登入方式可用,所以引導重點是「改用其他方式」(而不是 ④ 的「需客服恢復」)。

如果沒設計師畫

FE 拿到 404 只能顯示通用「Apple 登入失敗」提示,用戶較難理解失敗原因與後續可行動作。

設計需求

  • 全頁版面
  • 文案
  • 替代登入方式按鈕的排列

⑥ 帳號自動合併成功 Toast

Apple / Google 都會用,既有 Google 已發生但 FE 從沒提示

出處(PRD 明文要求)

  • PRD line 100(§5 S2 場景):「用戶以相同 email 但不同 provider 登入時,系統自動合併到既有帳號,並顯示一次性 Toast 通知」← Toast 明寫
  • PRD line 120(BR-018):「自動合併除 in-app Toast 外,另寄送 audit 通知信」← 雙重通知(Toast + 信)明寫
  • 結論:Toast 通知是 PRD 明文要求;Toast 樣式(success vs info 等級)/ 文案 / 自動消失時長由設計師補圖

場景

阿明三年前用 ming@gmail.com + 密碼註冊 wport。今天他點「用 Google 登入」(Google 帳號也是 ming@gmail.com,已驗證)。

BE 自動把 Google 綁到他既有 wport 帳號上(auto-merge),他登入後所有舊資料還在(履歷、應徵紀錄)。

用戶會看到

登入成功後顯示 Toast:「我們發現你已有 wport 帳號(建立於 2023),已自動把 Google 登入綁定到該帳號」+ 自動消失。

為什麼新加

既有 Google 也會 auto-merge,但 FE 完全沒提示,用戶可能困惑為什麼「第一次」用 Google 登入就有舊資料(懷疑是 bug 或資料外洩)。

如果沒設計師畫

用戶體感會是「我第一次用 Google 登入怎麼有資料?是不是看到別人的帳號?」,可能轉成客服詢問或自行嘗試修正。

設計需求

  • Toast 樣式(success vs info 等級)
  • 文案(簡短說明「不是 bug,是把你新登入方式綁到既有帳號」)
  • 自動消失時長

不需設計師畫面、但 PM 要拍板的 3 個 UX 決定

以下 3 個情境不會出現新畫面(沿用既有元件),但體驗細節需 PM 決定方向。

A. 用戶閒置太久才按綁定按鈕

場景:阿明點「綁定 Google」→ 跳 Google 驗證視窗 → 阿明完成 Google 驗證後離開電腦 → 6 分鐘後回來才點 wport 的 [確認綁定] 按鈕。

會發生什麼:後端會擋下,認為「身份驗證時間太久(超過 5 分鐘),請重新驗證」。

PM 要拍板

  • A1. FE 自動再開一次 Google 驗證視窗(順暢但用戶可能困惑「為什麼又跳一次」)
  • A2. 顯示提示文字讓用戶手動再點(清楚但多一個點擊步驟)

體驗影響:低(發生率不高,但會出現)。

B. Apple 用戶首次登入剛好遇到後端短暫繁忙

場景:小美第一次用 Apple 註冊 wport,後端要把 Apple 給的 email 存進資料庫時,剛好遇到 DB 短暫繁忙寫入失敗。後端會自動重試,但會花 30 秒。

會發生什麼:FE 收到「處理中」提示,30 秒後再重試一次。

PM 要拍板

  • 可接受用戶等 30 秒嗎?(不接受的話需另外設計「先讓他進站、之後背景補寫」的複雜流程,工本高得多)
  • 30 秒等待時 UI 顯示什麼文案?建議「Apple 登入處理中,請稍候…」之類

體驗影響:極低(DB 寫入失敗率本身很低,且只影響「第一次用 Apple 註冊」當下)。

C. 帳號管理頁要不要顯示新增的 7 個欄位

場景:本次後端 GET /auth/login-methods(帳號管理「登入方式」列表)會多回 7 個欄位,包含:

  • 這個第三方帳號第一次綁定的時間
  • 最近一次用這個方式登入的時間
  • 這是不是 Apple Hide My Email 的 relay 信箱
  • 是不是從舊資料 migration 過來的(無精確綁定時間)
  • 可不可以解綁(用於 ② 按鈕 disabled 狀態)
  • 等等

PM 要拍板

  • 帳號管理頁要不要新增 UI 顯示這些資訊?例如「您於 2024 年綁定 Google,最近登入 5/17」
  • 還是後端先給、FE 先收著不顯示,未來再做?

體驗影響:低(不做也不會壞,就是現在的樣子)。若做,可提升帳號透明度 / 安全感。


一句話 summary

Apple 登入做的事情跟 Google 行為一樣,但用戶會看到的畫面狀態有 6 個是新的:①step-up 彈窗 ②解綁 disabled ③Apple relay banner ④客服恢復全頁 ⑤外部撤銷 ⑥auto-merge toast。

①②⑥ Google 也會用到,③④⑤ 是 Apple 獨有。PM 決策:6 項皆 FE 依 PRD §6 + §10.5 實作,不另開設計/Storybook;⑤ 做 Toast 不做全頁。