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.
97 lines
3.6 KiB
Markdown
97 lines
3.6 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
# 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).
|