Auth API

Mounted at /api/auth on port 8716. asyncat uses local bcrypt + JWT — no external auth service.

Endpoints

MethodPathAuthDescription
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.