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 truth:doc/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 + tooltip | 否 | 依 can_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 做 Toast(BINDING_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 Statusentity,狀態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 做 Toast(
BINDING_REVOKED_BY_PROVIDER),不做下方原述之全頁。以下保留 RD handoff 背景說明。
Apple 獨有(技術上 Google 也可能但實務罕見)
出處(PRD 提及行為、UI 細節由 spec 補)
- PRD line 220(BR-031
consent-revokedevent):「等同 ACT-8 解綁 Apple 路徑(含 BR-029 二層傳播)」+「wport 帳號保留(用戶可用其他登入方式取回)」 - PRD line 221(BR-031
account-deleteevent):同上「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 不做全頁。