WebAuthn Passkey 案例研究
本案例研究透過複雜功能範例展示規格框架:為影像監控平台後端新增 WebAuthn passkey 身分驗證。本案例研究突顯與第三方身分識別提供者(AWS Cognito)整合以及管理破壞性約束的挑戰。
高階規格(提案)
提案捕捉業務意圖、技術約束與破壞性變更影響。
# Change Proposal: Add WebAuthn Passkey Support
## Why
Users increasingly expect passwordless authentication options for better security
and user experience. Passkeys (WebAuthn) provide phishing-resistant authentication
that's more secure than traditional passwords and easier for users. AWS Cognito
added native support for passwordless authentication including passkeys in
November 2024, making this a viable enhancement for the platform.
## What Changes
- Add WebAuthn/passkey authentication as an alternative first-factor method
- Implement passkey registration workflow (up to 20 passkeys per user)
- Add GraphQL APIs for passkey management (register, list, delete)
- Modify authentication flow to support password and passwordless paths
- Add organization-level setting `passkeyEnabled` (default false)
## Impact
### Affected Specs
- NEW: authentication/passkey-management
- MODIFIED: organization-settings (add passkeyEnabled flag with MFA constraint)
### Breaking Changes
- **BREAKING**: Organizations with `isRequiredMFA=true` cannot enable passkey
authentication (AWS Cognito constraint: MFA and passwordless are mutually exclusive)
- Organizations must choose between enforced MFA or passkey support
- Users with personal MFA enabled cannot authenticate with passkeys
### Dependencies
- AWS Cognito Essentials or Plus plan (Lite plan does not support passkeys)
- Frontend must implement WebAuthn browser APIs
- Choice-based authentication flow configuration in Cognito
### Migration
- No data migration required for existing users
- Organizations wanting passkeys must disable MFA enforcement first
- Feature flag for controlled rollout關鍵特性:
- 明確識別平台約束(Cognito MFA/passkey 互斥性)
- 以清楚的影響範圍分類破壞性變更
- 列出影響實作選擇的外部相依性
設計文件
設計文件捕捉由外部平台約束驅動的架構決策。
# Design Document: WebAuthn Passkey Support
## Context
Vortex Backend uses AWS Cognito for user authentication with two MFA mechanisms:
1. **User-level MFA**: Individual users enable TOTP via `AdminSetUserMFAPreference`
2. **Organization-level MFA**: Organizations require all users to use MFA via
`isRequiredMFA` flag
AWS Cognito constraint (November 2024 documentation):
> "If you require multi-factor authentication (MFA) in your user pool,
> you cannot use passwordless authentication."
## Goals / Non-Goals
### Goals
- Enable passwordless authentication using WebAuthn passkeys
- Support passkey registration, listing, and deletion
- Maintain backward compatibility with password + MFA authentication
- Provide clear configuration options for organizations
### Non-Goals
- Replace existing password-based authentication
- Modify existing TOTP MFA implementation
- Custom WebAuthn implementation (will use Cognito native support)
- Passkey-based MFA (AWS Cognito doesn't support this)
## Decisions
### Decision 1: Use Cognito Native Passkey Support
**Choice:** Use AWS Cognito's native WebAuthn support rather than custom implementation.
**Rationale:**
- Reduces implementation complexity and security risks
- Leverages AWS's managed infrastructure and compliance
- Native integration with existing user pools
- Built-in support for standard WebAuthn APIs
**Alternatives Considered:**
- Custom WebAuthn with Lambda: Rejected due to security audit requirements
- Third-party service (Okta): Rejected to avoid vendor migration costs
### Decision 2: MFA and Passkey Mutual Exclusivity at Organization Level
**Choice:** Add `passkeyEnabled` boolean (default false) with validation:
`isRequiredMFA && passkeyEnabled` cannot both be true.
**Rationale:**
- AWS Cognito enforces this at the user pool level
- Clear separation prevents user confusion
- Explicit opt-in for passkey functionality
**Alternatives Considered:**
- Auto-disable MFA when passkeys enabled: Too dangerous (security downgrade)
- Separate user pool for passkey users: Too complex (data sync issues)
### Decision 3: Support Both ES256 and RS256 Algorithms
**Choice:** Accept both ES256 (-7) and RS256 (-257) for passkey registration.
**Rationale:**
- Maximizes device compatibility (different platforms prefer different algorithms)
- Cognito supports both; no security downside
### Decision 4: Support Synced and Device-bound Passkeys
**Choice:** Allow both device-bound and synced passkeys (iCloud Keychain, Google).
**Rationale:**
- Better UX (passkeys work across user's devices)
- Industry trend toward synced passkeys for usability
- Users choose based on security/convenience preference
## Risks
### Risk 1: Organizations Cannot Use Both MFA and Passkeys
**Impact:** Organizations requiring MFA for compliance must choose between
enforcement and passkey convenience.
**Mitigation:**
- Document constraint clearly in admin UI
- Provide migration guide
- Monitor AWS Cognito roadmap for future support
### Risk 2: User Lockout
**Impact:** Users might lose access if they lose passkey device without backup.
**Mitigation:**
- Allow multiple passkeys per user (up to 20)
- Encourage synced passkeys
- Always keep password authentication as backup關鍵特性:
- 將外部平台約束記錄為一等關注點
- 每個決策追溯至平台限制或安全考量
- 風險承認團隊無法控制的約束
領域規格
領域規格以涵蓋約束的情境定義需求。
# Authentication Capability: WebAuthn Passkey Support
## Requirement: Passkey Registration Challenge
The system SHALL provide an API to initiate passkey registration.
#### Scenario: User requests passkey registration challenge
- **GIVEN** a user is authenticated
- **AND** the organization has `passkeyEnabled=true`
- **WHEN** the user requests a registration challenge via `registerPasskeyChallenge`
- **THEN** the system SHALL return challenge ID and WebAuthn options
- **AND** the challenge SHALL be valid for 5 minutes
#### Scenario: Organization has passkeys disabled
- **GIVEN** a user belongs to an organization with `passkeyEnabled=false`
- **WHEN** the user requests a passkey registration challenge
- **THEN** the system SHALL return error "PASSKEYS_NOT_ENABLED"
## Requirement: Passkey Registration Completion
The system SHALL accept and verify WebAuthn credentials.
#### Scenario: Valid passkey credential submitted
- **GIVEN** a user has requested a registration challenge
- **WHEN** the user submits valid signed credential within 5 minutes
- **THEN** the system SHALL verify the credential with AWS Cognito
- **AND** store the passkey in the user's account
- **AND** return success with passkey metadata
#### Scenario: Maximum passkeys limit reached
- **GIVEN** a user has 20 registered passkeys
- **WHEN** the user attempts to register another passkey
- **THEN** the system SHALL return error "MAX_PASSKEYS_REACHED"
## Requirement: Passkey Listing
The system SHALL provide API to list user's registered passkeys.
#### Scenario: User lists their passkeys
- **GIVEN** a user has registered passkeys
- **WHEN** the user queries via `listPasskeys`
- **THEN** the system SHALL return passkey metadata including:
- Passkey ID, Credential ID, Friendly name
- Creation timestamp, Last used timestamp
- Supported transports
## Requirement: MFA and Passkey Mutual Exclusivity
The system SHALL enforce mutual exclusivity between MFA requirement and passkeys.
#### Scenario: Enable passkeys when MFA not required
- **GIVEN** an organization has `isRequiredMFA=false`
- **WHEN** admin sets `passkeyEnabled=true`
- **THEN** the system SHALL update the setting
- **AND** users can register passkeys
#### Scenario: Attempt to enable passkeys with required MFA
- **GIVEN** an organization has `isRequiredMFA=true`
- **WHEN** admin attempts to set `passkeyEnabled=true`
- **THEN** the system SHALL reject with error "MFA_PASSKEY_CONFLICT"
- **AND** return message explaining the constraint
#### Scenario: Attempt to require MFA with passkeys enabled
- **GIVEN** an organization has `passkeyEnabled=true`
- **WHEN** admin attempts to set `isRequiredMFA=true`
- **THEN** the system SHALL reject with error "MFA_PASSKEY_CONFLICT"關鍵特性:
- 約束情境(MFA/passkey 衝突)視為一等需求
- 為前端整合指定錯誤碼
- 包含安全需求(稽核記錄)
規格可追溯性
Passkey 功能展示透過約束驅動實作的可追溯性:
意圖:「使用者需要無密碼身分驗證以獲得更好的安全性與使用者體驗」
│
├── 提案(proposal.md)
│ ├── 識別 AWS Cognito 約束
│ └── 分類破壞性變更(MFA/passkey 互斥性)
│
├── 設計文件(design.md)
│ ├── 4 個架構決策
│ ├── 外部約束記錄為一等關注點
│ └── 合規性驅動組織的風險分析
│
├── 領域規格
│ ├── authentication/passkey-management(NEW)
│ │ ├── 6 個需求、15+ 個情境
│ │ └── 約束情境作為需求
│ └── organization-settings(MODIFIED)
│ └── passkeyEnabled 旗標含驗證
│
└── 實作任務(tasks.md)
└── 12 個任務群組、50+ 個個別任務結案報告:策略相依性與隱形成本
結果: Passkey 提案最終因以下原因取消:(1) 沒有 Cognito 方案升級的預算,以及 (2)「One Account」計畫被認定為長期解決方案。
此結果揭露了規格驅動工作流程應處理的關鍵組織模式:
隱藏的相依性問題
發現時程(AI 加速):
───────────────────────────────────────
第 1 天:工程提出 passkey 功能
第 2 天:AI 輔助調查發現 Cognito MFA/passkey 約束
第 3 天:AI 輔助成本分析與設計文件完成
第 6 天:PM Team 透露「One Account」(Okta 遷移)已在規劃中(但無實際時程跟計劃)
→ 工程團隊不知道這會影響所有身分驗證相關變更
→ 提案以「拋棄式工作」為由取消AI 如何加速發現
規格驅動工作流程搭配 AI 代理,將傳統需要數月的工作壓縮至數天:
| 階段 | 傳統時程 | AI 輔助時程 | 加速倍數 |
|---|---|---|---|
| 提案草稿 | 1-2 週 | 1 天 | 7-14x |
| 技術調查 | 2-4 週 | 1 天 | 14-28x |
| 設計文件 | 1-2 週 | 1 天 | 7-14x |
| 任務拆解(50+ 任務) | 1 週 | 數小時 | 10-20x |
| 到達決策點總計 | 5-9 週 | 4 天 | 9-16x |
悖論: AI 加速比傳統流程更快地暴露了策略阻擋因素(One Account)。若無 AI 輔助,團隊可能花費 5-9 週進行調查才發現相同的阻擋因素——這是顯著更高的沉沒成本。
AI 加速的真正價值
快速失敗優於緩慢失敗。在 4 天內發現策略阻擋因素相較於 5-9 週,節省了大量組織資源並讓團隊能快速轉向。
AI 輔助的規格工作即使在提案取消時也產生有價值的產出物:
- 完整的技術調查已記錄(Cognito 約束、MFA 互動)
- 設計決策與替代方案保留供未來參考
- 50+ 實作任務已定義——若計畫解除阻擋即可使用
- 決策理由已捕捉供組織學習
- 投入並非完全「浪費」——知識以機器可讀格式保留
關鍵學習
策略計畫的可見性:長期計畫(One Account、Privilege 2.0)必須在共享路線圖中可見,工程在建立提案時可查閱
等待的成本:「等待 X」的決策應包含 X 被延遲或取消的風險評估
需求管道:需要明確流程處理前線驅動與工程驅動的改善
模式識別:組織應追蹤「被未來計畫阻擋」的模式以識別系統性規劃問題
框架新增: 被策略計畫阻擋的規格應以「BLOCKED_BY_INITIATIVE」狀態歸檔,並設定定期審查觸發器以重新評估阻擋計畫是否仍在正軌。
為何此案例研究重要
外部約束:展示如何在規格中處理第三方平台限制(AWS Cognito MFA/passkey 互斥性)
破壞性變更:展示影響組織配置的破壞性變更的明確分類與溝通
合規性影響:說明安全合規性需求(MFA 強制)如何與功能啟用互動
多層級協調:後端變更需要前端 WebAuthn 實作、基礎設施配置與謹慎部署
代理脈絡:AI 代理需要完整的約束鏈才能產生正確的驗證邏輯與錯誤處理
另一個案例: E-Map 平面圖