Authentication API

Status: Implemented (Milestone 7)

Email/password authentication with JWT access tokens and refresh sessions.

Endpoints

MethodPathDescription
POST/api/auth/registerCreate account and session
POST/api/auth/loginAuthenticate and create session
POST/api/auth/refreshRotate refresh token and issue new access token
POST/api/auth/logoutRevoke refresh session

Register / Login

Request:

{
  "email": "user@example.com",
  "password": "password123"
}

Response (201 for register, 200 for login):

{
  "token": "<access-jwt>",
  "refreshToken": "<opaque-refresh-token>",
  "user": {
    "id": "usr_550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "role": "authenticated",
    "createdAt": "2026-06-09T12:00:00.000Z"
  }
}

passwordHash is never returned.

Refresh / Logout

Request:

{
  "refreshToken": "<opaque-refresh-token>"
}

Refresh returns the same shape as login. Logout returns 204 No Content.

Authenticated Requests

Send the access token on collection CRUD requests:

Authorization: Bearer <access-jwt>

Status Codes

CodeWhen
200Login or refresh succeeded
201Registration succeeded
204Logout succeeded
400Invalid JSON or missing fields
401Invalid credentials or token
409Email already registered

Error Codes

CodeDescription
unauthorizedInvalid email/password or token
conflictDuplicate email on register
bad_requestInvalid request body

Events

EventWhenPayload
auth.registerSuccessful registrationSafe user object
auth.loginSuccessful loginSafe user object
auth.logoutSuccessful logout{ userId }

Configuration

bakend.json:

{
  "auth": {
    "jwtSecret": "change-me-in-production",
    "accessTokenTtl": "15m",
    "refreshTokenTtl": "7d"
  }
}

Environment overrides:

  • BAKEND_AUTH_JWT_SECRET
  • BAKEND_ADMIN_EMAIL โ€” first registration with this email receives the admin role

Example

curl -X POST http://localhost:8080/api/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"email":"user@example.com","password":"password123"}'

curl -X POST http://localhost:8080/api/posts \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{"title":"Hello"}'

See Authentication user guide and REST API for collection permissions.