Add FIDO2/WebAuthn passkey authentication
Phase 14: Full WebAuthn support for passwordless passkey login and hardware security key 2FA. - go-webauthn/webauthn v0.16.1 dependency - WebAuthnConfig with RPID/RPOrigin/DisplayName validation - Migration 000009: webauthn_credentials table - DB CRUD with ownership checks and admin operations - internal/webauthn adapter: encrypt/decrypt at rest with AES-256-GCM - REST: register begin/finish, login begin/finish, list, delete - Web UI: profile enrollment, login passkey button, admin management - gRPC: ListWebAuthnCredentials, RemoveWebAuthnCredential RPCs - mciasdb: webauthn list/delete/reset subcommands - OpenAPI: 6 new endpoints, WebAuthnCredentialInfo schema - Policy: self-service enrollment rule, admin remove via wildcard - Tests: DB CRUD, adapter round-trip, interface compliance - Docs: ARCHITECTURE.md §22, PROJECT_PLAN.md Phase 14 Security: Credential IDs and public keys encrypted at rest with AES-256-GCM via vault master key. Challenge ceremonies use 128-bit nonces with 120s TTL in sync.Map. Sign counter validated on each assertion to detect cloned authenticators. Password re-auth required for registration (SEC-01 pattern). No credential material in API responses or logs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -744,6 +744,79 @@ See ARCHITECTURE.md §21 (Token Issuance Delegation) for design details.
|
||||
|
||||
---
|
||||
|
||||
## Phase 14 — FIDO2/WebAuthn and Passkey Authentication
|
||||
|
||||
**Goal:** Add FIDO2/WebAuthn support for passwordless passkey login and hardware
|
||||
security key 2FA. Discoverable credentials enable passwordless login;
|
||||
non-discoverable credentials serve as 2FA. Either WebAuthn or TOTP satisfies
|
||||
the 2FA requirement.
|
||||
|
||||
### Step 14.1: Dependency, config, and model types
|
||||
**Acceptance criteria:**
|
||||
- `github.com/go-webauthn/webauthn` dependency added
|
||||
- `WebAuthnConfig` struct in config with RPID, RPOrigin, DisplayName
|
||||
- Validation: if any field set, RPID+RPOrigin required; RPOrigin must be HTTPS
|
||||
- `WebAuthnCredential` model type with encrypted-at-rest fields
|
||||
- Audit events: `webauthn_enrolled`, `webauthn_removed`, `webauthn_login_ok`, `webauthn_login_fail`
|
||||
- Policy actions: `ActionEnrollWebAuthn`, `ActionRemoveWebAuthn`
|
||||
|
||||
### Step 14.2: Database migration and CRUD
|
||||
**Acceptance criteria:**
|
||||
- Migration 000009: `webauthn_credentials` table with encrypted credential fields
|
||||
- Full CRUD: Create, Get (by ID, by account), Delete (ownership-checked and admin),
|
||||
DeleteAll, UpdateSignCount, UpdateLastUsed, Has, Count
|
||||
- DB tests for all operations including ownership checks and cascade behavior
|
||||
|
||||
### Step 14.3: WebAuthn adapter package
|
||||
**Acceptance criteria:**
|
||||
- `internal/webauthn/` package with adapter, user, and converter
|
||||
- `NewWebAuthn(cfg)` factory wrapping library initialization
|
||||
- `AccountUser` implementing `webauthn.User` interface
|
||||
- `EncryptCredential`/`DecryptCredential`/`DecryptCredentials` round-trip encryption
|
||||
- Tests for encrypt/decrypt, interface compliance, wrong-key rejection
|
||||
|
||||
### Step 14.4: REST endpoints
|
||||
**Acceptance criteria:**
|
||||
- `POST /v1/auth/webauthn/register/begin` — password re-auth, returns creation options
|
||||
- `POST /v1/auth/webauthn/register/finish` — completes registration, encrypts credential
|
||||
- `POST /v1/auth/webauthn/login/begin` — discoverable and username-scoped flows
|
||||
- `POST /v1/auth/webauthn/login/finish` — validates assertion, issues JWT
|
||||
- `GET /v1/accounts/{id}/webauthn` — admin, returns metadata only
|
||||
- `DELETE /v1/accounts/{id}/webauthn/{credentialId}` — admin remove
|
||||
- Challenge store: `sync.Map` with 120s TTL, background cleanup
|
||||
|
||||
### Step 14.5: Web UI
|
||||
**Acceptance criteria:**
|
||||
- Profile page: passkey enrollment form, credential list with delete
|
||||
- Login page: "Sign in with passkey" button with discoverable flow
|
||||
- Account detail page: passkey section with admin remove
|
||||
- CSP-compliant `webauthn.js` (external script, base64url helpers)
|
||||
- Empty state handling for zero credentials
|
||||
|
||||
### Step 14.6: gRPC handlers
|
||||
**Acceptance criteria:**
|
||||
- Proto messages and RPCs: `ListWebAuthnCredentials`, `RemoveWebAuthnCredential`
|
||||
- gRPC handler implementation delegating to shared packages
|
||||
- Regenerated protobuf stubs
|
||||
|
||||
### Step 14.7: mciasdb offline management
|
||||
**Acceptance criteria:**
|
||||
- `mciasdb webauthn list --id UUID`
|
||||
- `mciasdb webauthn delete --id UUID --credential-id N`
|
||||
- `mciasdb webauthn reset --id UUID` (deletes all)
|
||||
- `mciasdb account reset-webauthn --id UUID` alias
|
||||
- All operations write audit events
|
||||
|
||||
### Step 14.8: OpenAPI and documentation
|
||||
**Acceptance criteria:**
|
||||
- All 6 REST endpoints documented in openapi.yaml
|
||||
- `WebAuthnCredentialInfo` schema, `webauthn_enabled`/`webauthn_count` on Account
|
||||
- ARCHITECTURE.md §22 with design details
|
||||
- PROJECT_PLAN.md Phase 14
|
||||
- PROGRESS.md updated
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
```
|
||||
@@ -760,7 +833,9 @@ Phase 0 → Phase 1 (1.1, 1.2, 1.3, 1.4 in parallel or sequence)
|
||||
→ Phase 11 (interleaved with Phase 3–4)
|
||||
→ Phase 12 (post Phase 3)
|
||||
→ Phase 13 (post Phase 3 and 11)
|
||||
→ Phase 14 (post v1.0.0)
|
||||
```
|
||||
|
||||
Each step must have passing tests before the next step begins.
|
||||
All phases complete as of v1.0.0 (2026-03-15).
|
||||
Phases 0–13 complete as of v1.0.0 (2026-03-15).
|
||||
Phase 14 complete as of 2026-03-16.
|
||||
|
||||
Reference in New Issue
Block a user