Zum Hauptinhalt springen

Auth API

Roestify verwendet Auth.js (NextAuth v5) mit JWT-Session-Strategie. Die Core-Auth-Endpunkte (/api/auth/*) werden von Auth.js automatisch bereitgestellt (Login, Callback, Session). Zusätzlich gibt es Custom-Endpunkte für Registrierung, Passwort-Reset und Einladungen.

POST /api/auth/register

Neuen Benutzer registrieren.

Rate Limit: 5 Requests / 5 Minuten / IP

Request:

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

Response (201):

{ "success": true }

Logik:

  1. Prüft ob Einladung existiert → Join Tenant
  2. Ohne Einladung → Neuen Trial-Tenant erstellen (14 Tage)
  3. E-Mail wird automatisch bestätigt

POST /api/auth/forgot-password

Passwort-Reset anfordern.

Rate Limit: 3 Requests / Stunde / E-Mail

Request:

{ "email": "user@example.com" }

Response (200): Immer { "success": true } (leakt nicht ob E-Mail existiert)

Logik:

  • Generiert 1-Stunden-Token
  • Sendet Reset-E-Mail via Resend

POST /api/auth/reset-password

Passwort zurücksetzen mit Token.

Rate Limit: 5 Requests / 5 Minuten / IP

Request:

{
"token": "abc123...",
"password": "neuesPasswort",
"confirmPassword": "neuesPasswort"
}

Response (200):

{ "success": true }

GET /api/v1/invitations/accept/{token}

Einladungstoken validieren (öffentlich, ohne Auth).

Rate Limit: 30 Requests / Minute / IP

Response (200):

{
"valid": true,
"email": "eingeladen@example.com",
"tenant_name": "Meine Rösterei",
"role": "roester"
}
StatusBedeutung
200Token gültig
404Token nicht gefunden
410Token bereits verwendet oder abgelaufen

POST /api/v1/invitations/accept/{token}

Einladung annehmen (authentifiziert).

Rate Limit: 10 Requests / Minute

Response (200):

{ "success": true }

Prüfungen:

  • E-Mail des eingeloggten Users muss mit Einladungs-E-Mail übereinstimmen
  • Multi-Workspace wird (noch) nicht unterstützt
  • Benachrichtigt Admins des Tenants

POST /api/v1/onboarding/setup

Onboarding-Wizard abschließen.

Rate Limit: 10 Requests / Minute

Request:

{
"company_name": "Meine Rösterei",
"country": "DE",
"timezone": "Europe/Berlin"
}

Response (200):

{ "success": true }

Nur einmal aufrufbar (Idempotenz-Check). Setzt onboarding_completed = true.