Skip to content

feat(auth): stabilize v1 auth infrastructure#275

Merged
justin13888 merged 18 commits into
masterfrom
v1-stabilize-auth
Mar 4, 2026
Merged

feat(auth): stabilize v1 auth infrastructure#275
justin13888 merged 18 commits into
masterfrom
v1-stabilize-auth

Conversation

@justin13888
Copy link
Copy Markdown
Collaborator

@justin13888 justin13888 commented Mar 3, 2026

Summary

This branch establishes the foundational scaffolding for the v1 auth stabilization epic (td-ee007c), setting up the sidecar/task management tooling and agent context needed to coordinate the full auth hardening effort.

Changes

  • Added sidecar/td tooling ignore patterns to .gitignore
  • Added AGENTS.md with mandatory task management instructions for AI agents
  • Linked CLAUDE.md to AGENTS.md for consistent agent context

Epic: Stabilize v1 Auth (td-ee007c)

This PR is part of the Stabilize v1 Auth epic, which encompasses the following work items:

Status Task
Reviewed Implement GET /auth/devices endpoint (td-c6d924)
Reviewed Fix race condition in user registration (td-fe6be1)
Reviewed Add rate limiting to auth endpoints (td-fbd167)
Reviewed Implement auth integration test suite (td-fb8bc9)
Reviewed Implement web auth context and token management (td-b7633d)
Reviewed Connect web login page to backend API (td-b755cc)
Reviewed Implement protected routes and auth guard in web app (td-076d43)
Reviewed Implement web MFA verification UIs — TOTP and passkey (td-a78578)
Reviewed Implement web password reset and account verification flows (td-8e557d)
Reviewed Add registered_via column to users table (td-ddf45d)
Reviewed Restrict CORS configuration for production (td-a04093)
Reviewed Externalize auth config values from hardcoded constants (td-22772d)
Reviewed Implement web user profile and device management UI (td-2999a5)

Test plan

TBD

Replaces todo!() in get_devices handler with full implementation that
lists active sessions for the authenticated user from the session store.

- Add last_active_at field to Session and Device structs
- Add get_sessions_for_user() to SessionManager (skips expired sessions)
- Handler validates bearer token, fetches user sessions, marks is_current
Adds a nullable registered_via VARCHAR(32) column to the users table.
Existing and seeded rows remain NULL; newly invited users will be set
to 'invitation' once the invite flow is implemented (td-cde837).

- Migration: m20250302_000000_add_registered_via
- Entity, model, service, auth, and GraphQL User types updated
Map sea_orm UniqueConstraintViolation errors from concurrent duplicate
registrations to RegisterError::UserAlreadyExists (409 Conflict) instead
of propagating them as unexpected 500 errors.
Remove EmailService placeholder, account_verified login gate, and all
related TODOs/stubs. Password reset token generation is preserved but
no longer attempts email delivery.
- Add Redis/in-memory rate limit storage with fixed-window counter
- Apply per-IP rate limiting: login (10/min), register (10/min)
- Apply per-email + per-IP rate limiting: password-reset-request (5/min)
- Return 429 with Retry-After header when limit exceeded
- Check failed_login_attempts and lock account after 10 failures (423)
- Add MAX_FAILED_LOGIN_ATTEMPTS and RATE_LIMIT_* constants
…ructure

- Rewrite all integration tests from axum to salvo TestClient API
- Fix common/mod.rs setup to use proper Valkey containers
- Add get_router_with_state() to lib.rs for test convenience
- Tests cover: register, login, token lifecycle, profile, password reset
- Fix missing Scope import in token service unit tests
- Add get_password_reset_token_by_email service query for test use
…om request

- Add totp_issuer to AuthConfig and ServerConfig, sourced from TOTP_ISSUER env var
- Update TotpService to use issuer from config instead of hardcoded constant
- Accept optional 'name' field in passkey finish_registration request body
- Update get_auth_issuer() to read from PIXLES_ISSUER env var
- Add token storage utilities (localStorage) in auth.ts
- Add typed API client with auto-refresh and 401 redirect in api.ts
- Add AuthProvider React context with TanStack Query for profile fetching
- Schedule proactive token refresh 60s before expiry
- Wrap root route with AuthProvider and QueryClientProvider
- Wire login form to POST /v1/auth/login with loading/error states
- Handle MFA_required response: show inline TOTP verification step
- Store received tokens via auth context and redirect to /photos
- Add AuthGuard component in root layout: redirects unauthenticated
  users to /login and suppresses protected content during auth check
- Redirect already-authenticated users away from /login to /photos
- Add WebAuthn browser API helpers with base64url<->ArrayBuffer conversion
- Add passkey login button to login page with full WebAuthn flow
- Add TotpEnroll component: shows QR code from provisioning_uri,
  confirms enrollment with a 6-digit code
- Add PasskeyRegister component: triggers browser credential creation
  and sends result to the API
- Install react-qr-code for TOTP enrollment QR display
- Add /forgot-password page: email form calls password-reset-request,
  shows confirmation without revealing if email exists
- Add /reset-password page: reads token from ?token= search param,
  validates and submits new password, shows success with login link
- Register both routes in routeTree.gen.ts
- Both routes are public (no auth required) per AuthGuard PUBLIC_PATHS
- Update Header: show user avatar with real name/email, working logout,
  links to /settings and /settings/security; Sign in button when logged out
- Add /settings page: edit username/email and change password via API
- Add /settings/security page:
  - Active sessions list from GET /auth/devices
  - TOTP enrollment and disable (with code verification)
  - Passkey management: list, delete, and add new passkeys
- Register new routes in routeTree.gen.ts
…S env var

Replace wildcard allow_origin("*") in auth and upload servers with
configurable origins loaded from ALLOWED_ORIGINS (comma-separated).
Defaults to ["*"] in debug builds and [] (deny all cross-origin) in
release builds. Both AuthConfig and UploadServerConfig now carry
allowed_origins from ServerConfig/environment.
…kout, TOTP, devices, and password-reset session revocation

- Add rate_limiting.rs: login/register (10 req/min) and password-reset (5 req/min per email+IP) with Retry-After header assertion
- Add account_lockout.rs: 10 DB-injected failures trigger 423 Locked; correct password still rejected; 9 failures do not lock; successful login resets counter
- Add totp.rs: full enrollment/verify-enrollment/disable/verify-login flows including max-attempt lockout (429) and provisioning-URI issuer check
- Add devices.rs: is_current flag correctness for single and multi-session scenarios; unauthenticated 401
- Add password_reset_sessions.rs: password reset revokes existing sessions; new login with reset password succeeds
- Fix totp-rs 5.7.0 API: TOTP::new now requires account_name and issuer arguments
@justin13888 justin13888 marked this pull request as ready for review March 4, 2026 21:30
@justin13888 justin13888 merged commit f5ffc53 into master Mar 4, 2026
1 check passed
@justin13888 justin13888 deleted the v1-stabilize-auth branch March 4, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant