FixVibe

// 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.

  1. 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 in NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY sicher; der Secret-Key darf niemals ein öffentliches Env-Präfix tragen und niemals in einer Client-Komponente erscheinen.
  2. Verifiziere, dass die Produktions-App pk_live_* verwendet, nicht pk_test_*. Test-Instanzen erlauben unverifizierte E-Mail-Adressen und deaktiviertes MFA — Test-Mode in Produktion auszuliefern ist ein Auth-Bypass.
  3. 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.
  4. 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.

  1. 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.
  2. 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.
  3. 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.
  4. Setze SameSite=Lax (Default) oder Strict auf dem Session-Cookie. Verifiziere in DevTools → Application → Cookies. SameSite=None ist 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.

  1. Verifiziere die Svix-Signatur bei jedem Webhook. Clerk-Webhooks werden von Svix signiert. Nutze new Webhook(secret).verify(body, headers). Lehne mit 401 ab, wenn die Verifizierung fehlschlägt.
  2. 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.
  3. Idempotenz in jedem Handler. Webhook-Zustellungen können sich wiederholen. Verwende den svix-id-Header als Primärschlüssel in einer webhook_events-Tabelle zur Deduplizierung. Wickle die Zustandsänderung und das Idempotenz-Insert in derselben Transaktion ab.
  4. Bei user.deleted PII 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.

  1. Lies auf jeder API-Route sowohl userId als auch orgId aus auth() und filtere Datenbank-Queries nach beidem. WHERE org_id = $orgId AND user_id = $userId. Vertraue nie einer org_id aus dem Request-Body.
  2. <strong>Use Clerk role checks for privileged operations, not boolean checks against the user object.</strong> <code>has({ role: 'org:admin' })</code> reads the role from the verified JWT. A user can spoof a boolean on a stale client object; they cannot spoof a JWT claim.
  3. 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 403 oder 404 sein.

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.

  1. Liste für jedes JWT-Template jeden Claim auf und bestätige, dass er notwendig ist. Dashboard → JWT Templates. Ein Template, das email und phone an Supabase sendet, legt PII jedem offen, der das JWT im Browser liest.
  2. 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.
  3. Verifiziere den Audience-Claim (aud) auf der empfangenden Seite. Supabase, Firebase, etc. sollten prüfen, dass aud dem 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.

  1. 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.
  2. 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

Lass einen FixVibe-Scan gegen deine Produktions-URL laufen — der baas.clerk-auth0-Check markiert Clerk-Publishable-Keys, Test-Keys in Produktion und gebündelte Secret-Keys. Für die äquivalente Checkliste zu Auth0 siehe Auth0-Sicherheits-Checkliste. Für den Gesamtüberblick über BaaS-Anbieter lies BaaS-Fehlkonfigurations-Scanner.

// scanne deine baas-oberfläche

Finde die offene Tabelle, bevor es jemand anderes tut.

Gib eine Produktions-URL ein. FixVibe ermittelt die BaaS-Anbieter, mit denen deine App spricht, identifiziert ihre öffentlichen Endpunkte und meldet, was ein nicht authentifizierter Client lesen oder schreiben kann. Kostenlos, ohne Installation, ohne Karte.

  • Kostenloser Tarif — 3 Scans pro Monat, ohne Anmeldekarte.
  • Passives BaaS-Fingerprinting — keine Domain-Verifizierung erforderlich.
  • Supabase, Firebase, Clerk, Auth0, Appwrite und mehr.
  • KI-Fix-Prompts bei jedem Befund — füge sie zurück in Cursor / Claude Code ein.
Kostenlosen BaaS-Scan starten

keine anmeldung erforderlich

Clerk-Sicherheits-Checkliste: 20 Punkte — Docs · FixVibe