// docs / baas security / clerk hardening
Clerk-Sicherheits-Checkliste: 20 Punkte
Clerk handhabt Auth, Sessions und Organisationen für deine App — was bedeutet, dass eine falsch konfigurierte Clerk-Integration ein Auth-Bypass, ein Session-Fixierungs-Vektor oder ein Org-Leakage-Pfad ist. Diese Checkliste ist ein 20-Punkte-Audit über Keys, Session-Konfig, Webhooks, Organisationen, JWT-Templates und laufendes Monitoring. KI-Coding-Tools verdrahten Clerk schnell mit vernünftigen Defaults; diese Liste fängt die Punkte, die sie auf dem Tisch liegen lassen.
Für Hintergrund, warum Fehlkonfigurationen auf Auth-Ebene eine Schwäche von KI-Tooling sind, siehe Warum KI-Coding-Tools Sicherheitslücken hinterlassen. Für die parallele Checkliste zu Auth0 siehe Auth0-Sicherheits-Checkliste.
Umgebungs-Keys und Origin-Allowlist
Clerk stellt zwei verschiedene Keys pro Projekt aus. Sie zu verwechseln oder zu leaken ist der erste Fehlermodus.
- Verwende den Publishable-Key (
pk_live_*in Produktion,pk_test_*in Dev) im Browser; verwende den Secret-Key (sk_live_*/sk_test_*) nur auf dem Server. Der Publishable-Key ist inNEXT_PUBLIC_CLERK_PUBLISHABLE_KEYsicher; der Secret-Key darf niemals ein öffentliches Env-Präfix tragen und niemals in einer Client-Komponente erscheinen. - Verifiziere, dass die Produktions-App
pk_live_*verwendet, nichtpk_test_*. Test-Instanzen erlauben unverifizierte E-Mail-Adressen und deaktiviertes MFA — Test-Mode in Produktion auszuliefern ist ein Auth-Bypass. - Konfiguriere die erlaubten Origins im Clerk-Dashboard. Settings → Domains → Allowed origins muss deine Produktionsdomain exakt listen. Leere oder Wildcard-Origin-Listen erlauben Angreifern, betrügerische Clerk-Frontends zu bauen, die mit deinem Backend sprechen.
- Rotiere den Secret-Key bei jedem Abgang oder Verdacht auf Leak. Dashboard → API Keys → Reset. Alter Key wird invalidiert; deploye serverseitigen Code mit dem neuen Wert vor der Rotation.
Session-Konfiguration
Session-Ablauf und Idle-Timeouts sind der Unterschied zwischen einer gestohlenen Session als 10-Minuten-Vorfall und einem 30-Tage-Vorfall.
- Setze den Session-Inaktivitäts-Timeout auf 30 Minuten oder weniger für SaaS-Apps, die sensible Daten verarbeiten. Dashboard → Sessions → Inactivity timeout. Bank-Tier-Apps sollten 5-10 Minuten verwenden; Standard-SaaS 30-60 Minuten; Consumer-Apps 1-7 Tage. Default ist 7 Tage.
- Aktiviere Session-Widerruf bei Passwortänderung, E-Mail-Änderung und MFA-Anmeldung. Dashboard → Sessions → Revoke on. Das sind nutzerinitiierte Sicherheitsereignisse; bestehende Sessions auf anderen Geräten sollten beendet werden.
- Verifiziere Sessions serverseitig auf jeder geschützten Route, nicht nur beim Sign-in. In Next.js:
const { userId } = await auth();in einer Server-Komponente / API-Route liest das JWT aus dem Cookie und validiert es. Vertraue niemals einer reinen Cookie-Prüfung. - Setze
SameSite=Lax(Default) oderStrictauf dem Session-Cookie. Verifiziere in DevTools → Application → Cookies.SameSite=Noneist ein CSRF-Vektor — verwende es nie, sofern du nicht explizit ein domainübergreifendes Auth-Setup konfiguriert hast.
Webhook-Verifizierung
Clerk-Webhooks feuern bei Lifecycle-Ereignissen des Nutzers (created, updated, deleted, session.ended). Sie sind der Synchronisierungsmechanismus für deine Datenbank — und ein gefälschter Webhook ist eine Schreib-Primitive für die Datenbank.
- Verifiziere die Svix-Signatur bei jedem Webhook. Clerk-Webhooks werden von Svix signiert. Nutze
new Webhook(secret).verify(body, headers). Lehne mit401ab, wenn die Verifizierung fehlschlägt. - Speichere das Webhook-Secret in einer Umgebungsvariablen, niemals im Code. Das Secret rotiert bei jeder Dashboard-Regeneration — dein Deploy muss es aus Env lesen, nicht aus einer Konstanten.
- Idempotenz in jedem Handler. Webhook-Zustellungen können sich wiederholen. Verwende den
svix-id-Header als Primärschlüssel in einerwebhook_events-Tabelle zur Deduplizierung. Wickle die Zustandsänderung und das Idempotenz-Insert in derselben Transaktion ab. - Bei
user.deletedPII binnen 24 Stunden hart löschen oder anonymisieren. GDPR / CCPA verlangen es. Auditiere den Löschpfad: welche Tabellen halten die Daten dieses Nutzers? Verwende FK ON DELETE CASCADE, wo möglich.
Organisationen und Berechtigungen
Wenn du Clerk Organizations nutzt, ist die Org-Grenze deine Tenant-Isolation. Jede serverseitige Query muss danach filtern.
- Lies auf jeder API-Route sowohl
userIdals auchorgIdausauth()und filtere Datenbank-Queries nach beidem.WHERE org_id = $orgId AND user_id = $userId. Vertraue nie einerorg_idaus dem Request-Body. - Verwende Clerk-Rollenprüfungen für privilegierte Operationen, nicht Boolean-Prüfungen gegen das User-Objekt.
has({ role: 'org:admin' })liest die Rolle aus dem verifizierten JWT. Ein Nutzer kann ein Boolean auf einem veralteten Client-Objekt fälschen; einen JWT-Claim kann er nicht fälschen. - Teste die Cross-Org-Isolation mit zwei echten Org-Konten. Erstelle Org A, befülle Daten, melde dich in Org B in einem anderen Browser an, versuche, die Daten von Org A über die API zu lesen. Antwort muss
403oder404sein.
JWT-Templates und externe Integrationen
JWT-Templates schieben Clerk-Identität in Supabase, Firebase und andere nachgelagerte Dienste. Falsch konfigurierte Templates teilen Claims über das Nötige hinaus oder legen Daten offen, die du nicht meintest.
- Liste für jedes JWT-Template jeden Claim auf und bestätige, dass er notwendig ist. Dashboard → JWT Templates. Ein Template, das
emailundphonean Supabase sendet, legt PII jedem offen, der das JWT im Browser liest. - Setze eine kurze Ablaufzeit auf JWT-Templates, die für clientseitige Downstream-Calls verwendet werden. 60 Sekunden für Downstream-API-Requests ist Standard. Längerlebige JWTs werden gestohlen und replayed.
- Verifiziere den Audience-Claim (
aud) auf der empfangenden Seite. Supabase, Firebase, etc. sollten prüfen, dassauddem erwarteten Service-Identifier entspricht. Ohne das kann ein für Service A ausgestelltes JWT sich gegen Service B authentifizieren.
Operatives Monitoring
Auth ist die signalstärkste Log-Quelle, die du hast. Beobachte sie.
- Alarmiere bei Spikes fehlgeschlagener Logins pro IP / pro Konto. Eine 50× normale Fehlerrate ist ein Credential-Stuffing-Angriff. Clerk emittiert diese Ereignisse an Webhooks; route sie an dein SIEM.
- Quartalsweise Überprüfung der Drift von Session- und Instance-Einstellungen. Defaults ändern sich mit Clerk-Updates; „alte Konfigurationen" werden mit der Zeit lautlos falsch. Vergleiche den JSON-Export des Dashboards mit deiner letzten bekannt-guten Kopie.
Nächste Schritte
Run a FixVibe scan against your production URL — it flags Clerk test keys in production and secret keys bundled into JavaScript. For the equivalent checklist on Auth0, see Auth0 security checklist. For the umbrella view across BaaS providers, read BaaS misconfiguration scanner.
