Dokumentation
Better Auth
Wie Motoko Base Authentifizierung mit Better Auth handhabt — E-Mail/Passwort, OAuth, Sessions, geschützte Routen, Verifizierung und Kontoverwaltung.
Motoko Base verwendet Better Auth für Authentifizierung. Sessions werden in PostgreSQL über den Drizzle-Adapter gespeichert. Es gibt keinen separaten Auth-Service — Postgres plus Env-Vars reichen für die lokale Entwicklung.
Auth-API-Routen sind unter /api/auth/* gemountet. Das Dashboard erfordert eine verifizierte Session vor dem Rendern.
Was out of the box mitgeliefert wird
| Feature | Status | Notes |
|---|---|---|
| Email / password sign-up | Enabled | Verification required before dashboard access |
| Email / password sign-in | Enabled | Redirects unverified users to /verify-email |
| Google OAuth | Optional | Enabled when GOOGLE_* env vars are set |
| GitHub OAuth | Optional | Enabled when GITHUB_* env vars are set |
| Email verification | Required | Sent on sign-up; resend on sign-in if still unverified |
| Password reset | Enabled | Requires Resend (RESEND_API_KEY, EMAIL_FROM) |
| Change password | Enabled | Settings → Security; revokes other sessions |
| Sign out | Enabled | User menu in the dashboard header |
| Session management | Enabled | List and revoke sessions in Settings → Security |
| Account linking | Enabled | Google and GitHub link to the same user when trusted |
Social-Sign-in-Buttons bleiben deaktiviert, bis OAuth-Credentials konfiguriert sind. Siehe OAuth-Setup für die schrittweise Provider-Einrichtung.
E-Mail und Passwort
Sign up (/sign-up) erfasst Name, E-Mail und Passwort. Better Auth erstellt den User und sendet eine Verifizierungs-E-Mail, wenn Resend konfiguriert ist.
Weil requireEmailVerification aktiv ist, meldet die Registrierung den User nicht automatisch an. Nach der Registrierung sehen sie einen „Check your email“-Screen und müssen vor dem Zugriff auf /dashboard verifizieren.
Sign in (/sign-in) akzeptiert E-Mail und Passwort. Bei Erfolg leitet der Client nach /dashboard um. Ist die E-Mail nicht verifiziert, gibt Better Auth 403 EMAIL_NOT_VERIFIED zurück und das Formular leitet nach /verify-email um.
Passwortregeln für Registrierung und Passwortänderung werden in src/features/dashboard/schemas/security.ts validiert (MIN_PASSWORD_LENGTH = 8 standardmäßig).
Google- und GitHub-OAuth
Beide Provider sind in src/lib/auth/auth.ts verdrahtet und werden nur aktiviert, wenn Env-Vars vorhanden sind. Der Client nutzt authClient.signIn.social({ provider: "google" | "github" }) aus den Sign-in- und Sign-up-Formularen.
OAuth-User werden typischerweise vom Provider als verifiziert markiert. Account Linking ist für Google und GitHub aktiviert, damit ein zurückkehrender Social-User an ein bestehendes E-Mail-Konto angehängt werden kann, wenn Better Auth dem Provider vertraut.
Vollständiges Provider-Setup: OAuth-Setup.
Sessions
Sessions werden in der Tabelle session gespeichert (src/lib/db/schema/auth.ts). Jede Session hat Token, Ablauf, IP und User-Agent.
Server-seitige Reads nutzen getCachedSession() aus src/lib/auth/session.ts. Es wrappt auth.api.getSession() in React cache(), damit Layout, Seiten und Server Actions derselben Anfrage eine Lookup teilen.
Client-seitige Calls nutzen authClient aus src/lib/auth/client.ts (Better Auth React Client).
Beispiel — Session in einer Server Component oder Action prüfen:
import { getCachedSession } from "@/lib/auth/session";
const session = await getCachedSession();
if (!session?.user?.id) {
// not signed in
}Geschützte Routen
Dashboard-Routen unter /dashboard sind in zwei Schichten geschützt:
src/proxy.ts— Edge-Gate für/dashboardund/dashboard/*. Leitet nicht authentifizierte User nach/sign-inund nicht verifizierte nach/verify-emailum.src/app/dashboard/layout.tsx— Server-Layout, das dieselben Checks vor dem Rendern der Shell wiederholt.
Einzelne Seiten und Server Actions rufen ebenfalls getCachedSession() auf und leiten um oder geben Fehler zurück, wenn nötig. Dieses Defense-in-Depth-Muster hält API-Routen und Actions sicher, auch wenn eine Seite den Check vergisst.
Um eine neue Route zu schützen, legen Sie sie unter src/app/dashboard/ ab (erbt Layout + Proxy) oder rufen Sie getCachedSession() auf und leiten manuell um.
E-Mail-Verifizierung
Verifizierung ist für den Dashboard-Zugang erforderlich.
| Step | What happens |
|---|---|
| Sign up | Better Auth sends a verification link via sendVerificationEmail |
| Click link | User is verified; they can sign in |
| Unverified sign-in | Redirect to /verify-email |
| Resend | /verify-email calls authClient.sendVerificationEmail |
E-Mail-Zustellung erfordert RESEND_API_KEY und EMAIL_FROM. Ohne Resend startet die App, aber Verifizierungs-E-Mails werden nicht gesendet — konfigurieren Sie E-Mail, bevor Sie die Registrierung lokal testen.
Der Inhalt der Verifizierungs-E-Mail liegt in src/lib/email/templates/verification-email.tsx. Der Send-Hook ist in src/lib/auth/auth.ts unter emailVerification.sendVerificationEmail.
Passwort-Reset
| Route | Purpose |
|---|---|
/forgot-password | Request a reset link |
/reset-password?token=… | Set a new password from the email link |
Ablauf:
- User sendet E-Mail auf
/forgot-password - Client ruft
authClient.requestPasswordResetmitredirectToauf/reset-passwordauf - Better Auth sendet die E-Mail über
sendResetPasswordinauth.ts - User öffnet den Link und sendet ein neues Passwort über
authClient.resetPassword
Reset-E-Mails erfordern Resend. Die Forgot-Password-Seite prüft die E-Mail-Konfiguration vor dem Senden.
Passwort ändern
Angemeldete User ändern ihr Passwort unter Settings → Security (/dashboard/settings/account/security).
Die UI ruft updatePasswordAction in src/features/dashboard/actions/security.ts auf, die auth.api.changePassword mit revokeOtherSessions: true nutzt — alle anderen Geräte werden nach erfolgreicher Änderung abgemeldet.
Passwortlängen-Limits kommen aus src/features/dashboard/schemas/security.ts.
Abmelden
Abmelden wird über das Dashboard-User-Menü ausgelöst. src/features/dashboard/components/dashboard-shell.tsx ruft auf:
await authClient.signOut({
fetchOptions: {
onSuccess: () => {
router.push("/sign-in");
router.refresh();
},
},
});Analytics- und Sentry-User-Kontext werden beim Abmelden im selben Handler geleert.
Konto- und Session-Verwaltung
Profile (Name, Avatar) — Settings → Profile (src/features/dashboard/components/settings/profile-settings-page.tsx).
Security (Passwort, Sessions) — Settings → Security:
- Passwort ändern
- Aktive Sessions auflisten (Browser, OS, letzte Aktivität)
- Einzelne Sessions widerrufen
- Alle anderen Sessions abmelden
Server-Logik liegt in src/features/dashboard/actions/security.ts (updatePasswordAction, revokeSessionAction (sessions load via src/features/dashboard/lib/security-settings.ts)).
Bei der Registrierung wird eine Willkommens-E-Mail aus dem Hook databaseHooks.user.create.after in auth.ts gesendet. Wenn Polar Billing konfiguriert ist, erstellt das Polar-Better-Auth-Plugin bei der Registrierung einen Billing-Kunden (src/lib/billing/providers/polar/auth-plugin.ts).
Wo ändere ich das?
Motoko Base teilt Auth auf in Server-Infrastruktur (src/lib/auth/), Auth-Seiten (src/app/…) und Kontoeinstellungen (src/features/dashboard/components/settings/). Es gibt keinen separaten Ordner src/features/auth/ — Auth-UI lebt in App-Routen; Kontoverwaltung lebt in Settings.
src/lib/auth/ — Server-Auth-Kern
| File | Change this when you want to… |
|---|---|
auth.ts | Enable/disable providers, toggle verification, customize email hooks, add Better Auth plugins, change account linking |
session.ts | Adjust how server components read the session (getCachedSession) |
client.ts | Configure the browser auth client (base URL is inferred automatically) |
social.ts | Change how Google/GitHub “configured” checks work |
safe-client-error.ts | Edit user-facing error messages for sign-in, sign-up, OAuth |
Der Catch-all-API-Handler ist src/app/api/auth/[...all]/route.ts — Sie müssen ihn selten bearbeiten.
Datenbanktabellen: src/lib/db/schema/auth.ts (user, session, account, verification).
Auth-Seiten — Sign-in, Sign-up, Wiederherstellung
| Path | Change this when you want to… |
|---|---|
src/app/sign-in/ | Sign-in form behavior, post-login redirect, OAuth handlers |
src/app/sign-up/ | Sign-up form, pending-verification UI |
src/app/verify-email/ | Resend verification UX |
src/app/forgot-password/ | Forgot-password form |
src/app/reset-password/ | Reset-password form |
src/components/ui/auth-section-3.tsx | Shared auth layout (fields, social buttons, styling) |
Sign-in- und Sign-up-Seiten übergeben googleEnabled / githubEnabled von isGoogleAuthConfigured() und isGitHubAuthConfigured(), damit Buttons automatisch deaktiviert werden, wenn OAuth nicht konfiguriert ist.
src/features/dashboard/components/settings/ — Konto und Sessions
| File | Change this when you want to… |
|---|---|
actions.ts | Password change, session list/revoke server actions |
config.ts | Password length limits, name length limits |
components/security-settings-page.tsx | Security UI (password form, session list) |
components/profile-settings-page.tsx | Profile name and avatar |
Route: src/app/dashboard/settings/account/security/page.tsx lädt Sessions serverseitig und rendert SecuritySettingsPage.
Routenschutz
| File | Change this when you want to… |
|---|---|
src/proxy.ts | Edge redirects for /dashboard (session + verification gate) |
src/app/dashboard/layout.tsx | Dashboard shell gate and user bootstrap |
Transaktions-E-Mail (auth-bezogen)
| File | Change this when you want to… |
|---|---|
src/lib/email/index.ts | Verification, reset, welcome send functions |
src/lib/email/templates/verification-email.tsx | Verification email content |
src/lib/email/templates/password-reset-email.tsx | Reset email content |
src/lib/email/templates/welcome-email.tsx | Welcome email content |
src/lib/email/templates/shared.tsx | Email brand name and layout |
Env-Vars für Auth: siehe Umgebungsvariablen.
Nächste Schritte
OAuth-Setup — Schrittweise Google- und GitHub-Konfiguration.
Umgebungsvariablen — Vollständige Env-Referenz inklusive BETTER_AUTH_* und OAuth-Keys.