Cookest
Backend API

Authentication

JWT-based auth flow — login, refresh, and protected endpoints

Authentication

Cookest uses a JWT access + refresh token pair. Access tokens are short-lived (15 min); refresh tokens are long-lived (30 days) and stored server-side as sha256(token).

Flow

Bearer token

All protected endpoints require:

Authorization: Bearer <access_token>

Token claims

{
  "sub": "uuid-of-user",
  "email": "user@example.com",
  "exp": 1234567890,
  "iat": 1234567800,
  "jti": "unique-token-id",
  "tier": "pro",
  "is_admin": false,
  "token_type": "access"
}

The tier claim allows client-side feature gating without an extra API call:

final payload = JwtDecoder.decode(accessToken);
final tier = payload['tier'] as String; // "free" | "pro" | "family"
if (tier == 'free') showUpgradePrompt();

Registration

POST /api/auth/register
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "securepassword",
  "name": "Alice"
}

Response: 201 Created — user created but not yet onboarded.

Login

POST /api/auth/login
Content-Type: application/json

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

Response:

{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 900
}

The refresh_token is set as an httpOnly cookie automatically.

Refresh

POST /api/auth/refresh
# Cookie: refresh_token=<token>  (sent automatically by browser/Dio)

Returns a new access_token. The refresh cookie is also renewed.

Logout

POST /api/auth/logout
Authorization: Bearer <access_token>

Invalidates the refresh token in the database.

Onboarding

After registration, complete the user profile:

POST /api/auth/onboarding
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "household_size": 2,
  "dietary_restrictions": ["vegetarian"],
  "allergies": ["nuts"],
  "health_goals": ["weight_loss"],
  "cooking_skill": "intermediate"
}

Security model

ConcernSolution
Password storageArgon2id (memory-hard)
Refresh token storageSHA-256 hash only — raw token never persisted
Access token storageClient memory only — never localStorage
Refresh token transporthttpOnly cookie — inaccessible to JS
Admin verificationAlways re-verified from DB — JWT claim not trusted alone
Rate limitinggovernor middleware on all endpoints

On this page