Pular para o conteúdo

Auth Worker

The auth worker provides email/password authentication using D1 for persistent user storage and KV for revocable opaque session tokens.

API Endpoints

MethodPathAuthDescription
POST/api/auth/register—Create account
POST/api/auth/login—Authenticate, receive session cookie
POST/api/auth/logout✅Destroy session
GET/api/auth/me✅Return current user
POST/api/auth/password✅Change password
GET/api/users/:id—Public user profile

All endpoints return JSON. CORS preflight is handled automatically.

Authentication

Set-Cookie: session={token}; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=604800; Domain=redecasas.com.br
  • Token: Random UUID stored in KV as session:{token}
  • TTL: 7 days (refreshed on GET /api/auth/me and POST /api/auth/password)
  • Storage: KV namespace shared across all workers
  • Logout: Cookie cleared with Max-Age=0; KV key deleted

Auth Middleware Flow

  1. Read Cookie: session={token}
  2. const session = await env.KV.get(session:${token})
  3. Parse JSON, check expiresAt
  4. Query D1: SELECT * FROM users WHERE id = ?
  5. Attach user to context for the handler

POST /api/auth/register

Create a new user account. No auth required.

Request body

{
"email": "user@example.com",
"password": "min8chars",
"name": "João Silva",
"phone": "11999999999"
}
FieldTypeRequiredRules
emailstring✅Valid email format
passwordstring✅8–128 characters
namestring❌Trimmed whitespace
phonestring❌10–11 digits (Brazilian format)

Response 201 Created

{
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "João Silva",
"phone": "11999999999"
}
}
  • Sets session cookie automatically on success
  • Returns 409 Conflict if email or phone already exists

POST /api/auth/login

Authenticate and receive a session cookie. No auth required.

Request body

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

Response 200 OK

{
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "João Silva",
"phone": "11999999999"
}
}
  • Sets session cookie
  • Returns 401 Unauthorized if credentials are wrong
  • Returns 403 Forbidden if account status === 'suspended'
  • Rate-limited per IP

POST /api/auth/logout

Destroy the current session. Requires auth.

Response 200 OK

{
"message": "Logged out successfully"
}

GET /api/auth/me

Return the current authenticated user. Requires auth.

Response 200 OK

{
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "João Silva",
"phone": "11999999999",
"status": "active",
"email_verified_at": "2026-01-15T10:00:00.000Z",
"stripe_customer_id": "cus_xxx",
"subscription_status": "active",
"subscription_period_end": "2026-07-01T00:00:00.000Z",
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-15T10:00:00.000Z"
}
}
  • Refreshes session TTL on success
  • subscription_status values: active, inactive, past_due, cancelled
  • status values: active, suspended, pending

POST /api/auth/password

Change the current user’s password. Requires auth.

Request body

{
"oldPassword": "currentpass",
"newPassword": "newpass123"
}

Response 200 OK

{
"message": "Password updated successfully"
}

GET /api/users/:id

Public user profile (no auth required).

Response 200 OK

{
"user": {
"id": "uuid",
"name": "João Silva",
"phone": "11999999999"
}
}
  • Returns 404 if user not found
  • Does NOT expose email, subscription status, or Stripe data

Security

Password Hashing

  • Algorithm: PBKDF2-HMAC-SHA-256
  • Iterations: 100,000
  • Salt: 32 bytes (random)
  • Key length: 32 bytes

This uses the Web Crypto API — no external dependencies.

Rate Limiting

  • 5 attempts per 15-minute window per IP on register and login
  • Implemented in src/ratelimit.ts

CORS

  • Access-Control-Allow-Credentials: true
  • Dynamic origin validation in shared/src/cors.ts

Session Storage (KV)

  • Key: session:{token}
  • Value: { userId, email, createdAt, expiresAt }
  • TTL: 7 days

Sessions are instantly revocable by deleting the KV key.

Development

Terminal window
cd auth-worker
npm run dev

Deployment

Terminal window
cd auth-worker && npm run deploy