Files
FTStore/web/AUTH.md
T
Felitendo 849e5e34b4 fix(web): require a valid session on every dashboard api route
The middleware gate is presence-only — it runs on the Edge runtime and can't
reach the database, so any non-empty `ftstore_session` cookie got past it.
Nine handlers relied on that alone and answered without `withAuth()`:
`/api/dashboard/*`, `/api/metrics/overview`, `/api/queue/{retry,batch}`,
`/api/entitlements` and `/api/privacy-cache`.

Wrap them. The only routes that stay open are the deliberately public ones:
`/api/auth/*`, `/api/health`, `/api/branding`, and the UA-gated
`/api/ftstore-{app,manager}/*` self-update proxies.
2026-08-03 14:05:20 +02:00

3.6 KiB

Authentication

FTStore Admin uses a session-based authentication system with user approval flow.

How It Works

  • Sessions: HTTP-only cookies (ftstore_session) with 30-day expiry
  • Passwords: Hashed with scrypt (Node.js crypto module, no external dependencies)
  • Middleware: Cookie-presence check on all routes (Edge-compatible, no DB calls)
  • Route protection: API routes wrapped with withAuth() / withAdmin() for DB-level auth

The middleware check is presence-only — it runs on the Edge runtime and cannot reach the database, so any non-empty ftstore_session value gets past it. withAuth() is what actually validates the session, which is why every non-public API route has to be wrapped. The only handlers that may stay unwrapped are the deliberately public ones: /api/auth/*, /api/health, /api/branding, and the User-Agent-gated /api/ftstore-app/* and /api/ftstore-manager/* self-update proxies.

This matters beyond the browser: FTStore Manager ships an on-device console that talks to these same routes, and its whole security model is that the app carries no credential — so a route that answers without a valid session is a hole in that model too.

First-User Setup

  1. Navigate to the application — you'll be redirected to /login
  2. Click "Register" to create the first account
  3. The first user is automatically an admin and approved
  4. All subsequent users require admin approval before they can log in

User Approval Flow

  1. New user registers at /register
  2. They see a "pending approval" message
  3. An admin goes to Settings > Users tab
  4. Admin clicks the checkmark to approve the user
  5. The user can now log in

User Roles

Role Permissions
admin Full access + user management (approve, role change, delete)
user Access to all dashboard features

Settings > Users Tab

Admins see a "Users" tab in Settings with:

  • User list with role/status badges
  • Approve/reject buttons
  • Role toggle (admin/user)
  • Delete user (with confirmation dialog)

Admins cannot demote themselves or delete their own account.

CLI User Management

For Docker deployments, manage users via CLI:

# Create a user
docker exec -it <container> npx tsx scripts/manage-users.ts create <username> <password>

# Create an admin user
docker exec -it <container> npx tsx scripts/manage-users.ts create <username> <password> --admin

# List all users
docker exec -it <container> npx tsx scripts/manage-users.ts list

# Approve a pending user
docker exec -it <container> npx tsx scripts/manage-users.ts approve <username>

# Change user role
docker exec -it <container> npx tsx scripts/manage-users.ts set-role <username> admin

# Reset password
docker exec -it <container> npx tsx scripts/manage-users.ts reset-password <username> <new-password>

# Delete a user
docker exec -it <container> npx tsx scripts/manage-users.ts delete <username>

API Endpoints

Method Endpoint Auth Description
POST /api/auth/register Public Register new user
POST /api/auth/login Public Login
POST /api/auth/logout Public Logout (clears session)
GET /api/auth/me Session Current user info
GET /api/users Admin List users
PUT /api/users Admin Update user (approve, role)
DELETE /api/users?id=N Admin Delete user

Session Cleanup

Expired sessions are automatically cleaned up when the cleanup action runs (Settings > Admin Actions > Run Cleanup, or via the worker's scheduled cleanup).