Auth API
Mounted at /api/auth on port 8716. asyncat uses local bcrypt + JWT — no external auth service.
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /api/auth/status | No | Returns auth metadata: mode, local account email, and whether first-run setup has been completed. |
POST | /api/auth/login | No | Authenticate with email + password. Returns { success, token, user }. Default: admin@local / changeme. |
POST | /api/auth/logout | No | Stateless logout — the server returns success immediately. The client discards the token. |
GET | /api/auth/me | Yes | Returns the current user's id, email, name, and profile picture. Fetches a fresh DB row so edits are reflected immediately. |
PUT | /api/auth/local-account | Yes | Update the local account name, email, and/or password. Returns a new token if email changed. Body: { name?, email?, password? } |
POST | /api/auth/update-password | Yes | Change the account password. Requires minimum 8 characters. Body: { password } |
POST | /api/auth/first-run | No | Issues a token automatically during first-run setup (before any workspace exists). Returns 403 once setup is complete. |
POST | /api/auth/register | No | Always returns 403 in the local build. Registration is disabled — use the seeded local account. |
Login example
curl -X POST http://localhost:8716/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@local","password":"changeme"}'
# 200 response:
# {"success":true,"token":"eyJ...","user":{"id":"...","email":"admin@local","name":null}}
JWT tokens
All protected endpoints require the token in the Authorization header:
Authorization: Bearer <token>
Tokens are signed with JWT_SECRET from den/.env and expire after JWT_EXPIRES_IN (default: 7d). There is no refresh endpoint — re-login to get a new token. asyncat is single-user by design so session expiry is rarely a concern.
Local auth model
asyncat uses a fully self-contained authentication system:
- Passwords are hashed with bcrypt (cost 12) and stored in the
users SQLite table. - JWTs contain
sub (user ID) and email claims only — no roles or permissions in the token. - The initial account (
admin@local) is seeded on first boot by den/src/db/seed.js. - Change the default password immediately: Settings → Account or via
PUT /api/auth/local-account.
Team mode (SOLO_MODE=false) is in progress and will add proper multi-user RBAC when complete. For now, asyncat is designed for a single local user.