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:
- Prüft ob Einladung existiert → Join Tenant
- Ohne Einladung → Neuen Trial-Tenant erstellen (14 Tage)
- 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"
}
| Status | Bedeutung |
|---|---|
| 200 | Token gültig |
| 404 | Token nicht gefunden |
| 410 | Token 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.