R
Docs
API Documentation

Authentication

Four cookie types, per-route role enforcement, and how to make authenticated calls.

1 min read Updated 5/28/2026developer

Overview

Restora 360 uses HTTP-only, HS256-signed JWT session cookies. Cookies are set on the platform host and (for tenant routes) the tenant subdomain. There are four distinct cookies so that, e.g. a super-admin signed into /admin and a tenant owner signed into a customer storefront in the same browser never collide.

API key authentication is on the roadmap (Phase 3 follow-up). Today all integration is session-cookie based — designed for first-party server-to-server scenarios.

The four cookies

| Cookie | Role | Used by | |---|---|---| | platform_session | tenant-owner / web-designer / sales-agent | Tenant dashboards, designer + agent portals | | admin_session | superadmin | Super-admin panel only (separate cookie to avoid collisions) | | customer_session | per-tenant customer | Tenant storefronts (registered customer accounts) | | ref_code | non-PII | First-touch sales-agent referral attribution (90-day TTL) |

Cookies are HttpOnly, SameSite=Lax, Secure in production, and JWT-signed with the platform's SESSION_SECRET env var.

Logging in

A successful POST to /api/auth/login sets platform_session (or admin_session if the user has role=superadmin). The response body returns { ok: true, role, tenantId? } — never the JWT itself.

Example — logged-in fetch

Shell
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"email":"owner@luigi.com","password":"password123"}' \
  -c cookies.txt \
  https://api.restora360.com/api/auth/login

# Subsequent calls reuse the cookie
curl -b cookies.txt https://api.restora360.com/api/tenant/luigi-pizza/orders

Role enforcement on the server

Every protected route calls one of the auth helpers (src/lib/auth/api-auth.ts):

  • requireTenantAccess(tenantId) — caller must own / co-manage the tenant, OR be a super-admin
  • requireSuperAdmin()admin_session only
  • requireWebDesigner()platform_session with role=web-designer
  • requireSalesAgent()platform_session with role=sales-agent
  • requireGroupAccess(orgId) — HQ-tenant owner OR group-manager with organizationId match
  • requireCustomerAuth(tenantId)customer_session scoped to the same tenant

Each returns either { session, ...context } or { error: Response }. Routes that don't guard are public.

Logging out

POST /api/auth/logout clears the relevant cookie (platform_session by default, admin_session when called from /admin/logout). Idempotent — calling it without a session is a no-op 200.

Frequently asked

  • Not yet. API keys are coming in a follow-up to Phase 3. Until then, persist a long-lived session by saving the `platform_session` cookie server-side and refreshing it before expiry (24-hour default TTL).