Commit Graph
7 Commits
Author SHA1 Message Date
mats 1decb5e53a go-auth: P3 interop captures — §13.5 TOTP + §14.4 WebAuthn golden fixtures
The remaining P3 tail is done:

- §13.5: three TOTP codes for the shared RFC secret computed by an
  independent implementation (Python stdlib, anchored to RFC 4226 App D
  counter 0 = 755224) at recorded wall-clock Unix seconds, pinned in
  platform/auth TestInteropCapturePythonTOTP — the Go code must produce
  identical codes at the same instants and VerifyWindow(0) must accept
  each at its capture time (cross-implementation agreement).
- §14.4: a full WebAuthn ceremony through real Chrome (navigator.credentials
  with a CDP virtual authenticator: ctap2/internal, resident key, UV,
  ES256) against a live go-auth instance — registration + passwordless
  login both completed via the RP handlers. The raw browser-produced
  blobs (clientDataJSON, attestationObject, authenticatorData, signature)
  are stored verbatim as a golden fixture and replayed by
  TestInteropCaptureChromeRegistration/Assertion: the parser must decode
  the real CBOR/COSE/authenticator-data, and the real ECDSA signature
  must verify over SHA-256(authData ‖ clientDataJSON) with the parsed key.

Plan doc §13.5/§14.4 updated with the recorded values; P3 row marked
complete. Both new suites green.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-09-01 14:49:15 +02:00
mats fd9446632d Add go-auth P3/D6: TOTP 2FA, WebAuthn passkeys, UsersManager
The authenticator-app second factor (D4, plan §5.7): shared RFC 4226/6238
primitive in platform/auth/totp.go (±1 window, monotonic replay floor, §13
RFC vectors), per-user AES-GCM-wrapped secrets under AUTH_TOTP_WRAP_KEY,
hashed one-shot recovery codes, and the password → /totp challenge (or
recovery) → session browser flow with first-login enrollment (otpauth QR via
vendored qrcode-generator, two-code confirm, once-only recovery reveal).
AUTH_REQUIRE_TOTP defaults on; per-challenge throttling (R5). Covered E2E by
internal/oidc/totp_flow_test.go.

Passkeys (D6, plan §5.8): go-auth is its own WebAuthn RP — hand-rolled
CBOR/COSE subset parser (stdlib only), register/login ceremonies with
attestation:none, per-request RP ID + origin derived from the issuer host,
AOF-backed cred:<user>:<credID> store. The /admin UsersManager (invite,
disable, reset password, list/rename/delete passkeys, enroll in-browser) is
session + admin-role gated. WebAuthn vectors + ceremony negatives in
internal/webauthn + webauthn_flow_test.go.

Also: bare-host GET / now redirects to /login (the issuer root otherwise
404s in a browser).

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-09-01 11:42:06 +02:00
mats 0f8ed97878 fix(auth): write the shared API-key store world-readable so other services see key changes
The key store holds only SHA-256 hashes + metadata (no plaintext keys) and is
read by other services in their own containers running as different non-root
uids. saveLocked wrote it 0600, so when the backoffice pod (running as root)
minted or revoked a key the file became root-owned 0600 — unreadable to the
ledger/cart services, freezing their mtime-reload snapshots: new keys 401'd
and revocations never took effect. Write 0644 so every reader reloads.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-08-17 21:53:37 +02:00
mats 0423723d43 feat(auth): GrantInfo — expose pending grant scopes + remaining TTL
The approve UI needs to show what a user code asks for and how long it
is valid; GrantInfo returns (scopes, secondsLeft, ok) without consuming
the grant (consumption stays one-shot in Token).
2026-08-16 14:29:22 +02:00
mats 2f3ea99745 feat(auth): minted keys + device login for the admin API and MCP endpoints
platform/auth gains the LocalJWT (HS256 mint/verify, AUTH_TOKEN_SECRET,
disabled when unset), the RFC 8628 DeviceFlow (start/approve/poll with
requested-scope gating) and KeyStore.ReloadIfChanged (mtime-based, so a
freshly minted key works across processes without a restart). One shared
store at /commerce/apikeys.json (AUTH_APIKEYS_FILE) now backs the
backoffice admin gate, the CMS API and every MCP endpoint; AUTH_TOKEN_SECRET
lets the companion app's device flow mint bearer tokens the same surfaces
accept. Submodule bumps: backoffice (AuthGate + device endpoints + mcp
scope), go-cart-actor (mcpauth sources), go-graph-cms-v2 (shared store +
token chain).

Also lands the still-pending receipt-ocr sidecar (previous pass): the
PP-OCR ONNX inference service + download-ocr-models.sh + k8s
deployment/initContainer, wired into compose and the ledger RECEIPT_OCR_URL,
with the extractor pairing fix riding the go-cart-actor bump.

Deploy: AUTH_APIKEYS_FILE/AUTH_TOKEN_SECRET/AUTH_DEVICE_BASE_URL on
backoffice + cart/profile/order/ledger in compose and k8s, /device ingress
route, stack-secrets AUTH_TOKEN_SECRET optional ref, docs updated.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-08-16 12:48:03 +02:00
mats 0db9705063 some 2026-08-02 19:18:59 +02:00
mats 2a66754f9e more platform 2026-06-29 12:35:32 +02:00