labstack / labstack/fanout

feat(auth): add passkeys (WebAuthn) like monk

Open
#87 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
HTML
Stars
4
Forks
0
Avg merge
4h 4m
Merged PRs (30d)
57

Description

Goal

Bring Fanout to parity with monk's auth stack: offer passkeys (WebAuthn / FIDO2) as a primary login method alongside the existing email-code flow.

Reference implementation: monk/server/src/monk/auth/webauthn.py + @simplewebauthn/browser on the client. ~440 lines of auth code total.

Why

  • Phishing-resistant by design (origin-bound credentials)
  • No password / OTP to type or intercept — users tap Touch ID / Windows Hello / security key
  • Platform support is now universal (Safari 16+, Chrome, Firefox, Edge, iOS 16+, Android)
  • Monk already ships it; feature parity is the bar

Proposed scope

Go side (est. ~400 LOC)
  • Library: github.com/go-webauthn/webauthn (FIDO2-compliant, maintained)
  • New SQLite tables (Atlas migration):
    • webauthn_credentials(id, user_id, credential_id, public_key, sign_count, aaguid, transports, created_at, last_used_at, name)
    • webauthn_challenges(id, user_id, challenge, purpose, expires_at) — ephemeral, 5 min TTL
  • New package: internal/auth/webauthn.go — helpers for registration + authentication ceremonies
  • New API endpoints in internal/api/auth.go:
    • POST /api/auth/passkey/register/options (admin-authenticated — starts registration)
    • POST /api/auth/passkey/register/verify (completes registration, persists credential)
    • POST /api/auth/passkey/login/options (anonymous — returns challenge for existing user)
    • POST /api/auth/passkey/login/verify (completes authentication, issues JWTs)
    • GET /api/auth/passkeys (list registered passkeys for current user)
    • DELETE /api/auth/passkeys/:id (revoke a passkey)
Config (env vars)
  • WEBAUTHN_RP_ID — Relying Party ID, e.g. fanout.labstack.com
  • WEBAUTHN_RP_NAME — display name, e.g. Fanout
  • Origins derived from HTTP_ADDR + WEBAUTHN_RP_ID
Client side (est. ~200 LOC)
  • Dep: @simplewebauthn/browser (already used by monk)
  • LoginPage: "Sign in with a passkey" button alongside the email input. If localStorage has a "prefer passkey" flag from a prior login, auto-launch the ceremony.
  • SettingsPage: new "Passkeys" section — list existing credentials, allow rename + revoke, "Add a passkey" button that triggers the registration ceremony.
Tests
  • Unit tests for the registration/authentication helpers
  • API tests for the four ceremony endpoints (challenge issuance, verification, replay rejection, counter-rollback detection)

Non-goals

  • Cross-device sign-in — out of scope for v1; default to platform authenticators
  • Passwordless-only mode (forcing passkey + disabling email codes) — keep both paths available
  • Account recovery via passkey — email codes remain the recovery path

Monk reference files (for implementation guidance)

  • monk/server/src/monk/auth/webauthn.py — ceremony helpers (89 lines)
  • monk/server/src/monk/auth/models.py — credential model (50 lines)
  • monk/server/src/monk/auth/dependencies.py — FastAPI auth deps (146 lines)
  • monk/web/src/... — client-side registration + login components

Open questions

  • Should passkey be required for new admin accounts (strict) or opt-in after email setup (flexible)?
  • Do we allow multiple passkeys per user from day one? (Monk does; recommended.)
  • Rename / revoke UX — simple list + buttons, or dedicated manage-passkeys page?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing internal/api/auth.go, the proposed internal/auth/webauthn.go package, Atlas migrations, and the monk WebAuthn reference files. Confirm the open questions about account policy, multiple passkeys, and rename/revoke UX before implementation. Done means the registration, login, listing, rename, and revoke flows work across LoginPage and SettingsPage, with ceremony, replay, and counter-rollback tests passing.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, javascript, sqlite
Domain
api, authentication, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.