Zum Inhalt springen

Better Auth auf Cloudflare ​

Ein leichtgewichtiger, TypeScript-basierter Authentifizierungsdienst, optimiert für Cloudflare Workers

Überblick über den Technologiestack ​

🔥 Hono
Ein schnelles, leichtgewichtiges Webframework auf Basis von Webstandards.

🔒 Better Auth
Ein umfassendes Authentifizierungsframework für TypeScript.

🧩 Drizzle ORM
Ein leichtgewichtiges, leistungsfähiges ORM für TypeScript mit Fokus auf die Entwicklererfahrung.

🐘 Postgres mit Neon
Eine für die Cloud optimierte, serverlose Postgres-Datenbank.

Vorbereitung ​

1. Installation ​

sh
# Hono
# > Select cloudflare-workers template
npm create hono

# Better Auth
npm install better-auth

# Drizzle ORM
npm install drizzle-orm
npm install --save-dev drizzle-kit

# Neon
npm install @neondatabase/serverless
sh
# Hono
# > Select cloudflare-workers template
pnpm create hono

# Better Auth
pnpm add better-auth

# Drizzle ORM
pnpm add drizzle-orm
pnpm add -D drizzle-kit

# Neon
pnpm add @neondatabase/serverless
sh
# Hono
# > Select cloudflare-workers template
yarn create hono

# Better Auth
yarn add better-auth

# Drizzle ORM
yarn add drizzle-orm
yarn add --dev drizzle-kit

# Neon
yarn add @neondatabase/serverless
sh
# Hono
# > Select cloudflare-workers template
bun create hono

# Better Auth
bun add better-auth

# Drizzle ORM
bun add drizzle-orm
bun add -d drizzle-kit

# Neon
bun add @neondatabase/serverless

2. Umgebungsvariablen ​

Setze die folgenden Umgebungsvariablen, um deine Anwendung mit Better Auth und Neon zu verbinden.

Siehe die offiziellen Anleitungen:

Erforderliche Dateien:

Plain
# Used by Wrangler in local development
# In production, these should be set as Cloudflare Worker Secrets.

BETTER_AUTH_URL=
BETTER_AUTH_SECRET=
DATABASE_URL=
Plain
# Used for local development and CLI tools such as:
#
# - Drizzle CLI
# - Better Auth CLI

BETTER_AUTH_URL=
BETTER_AUTH_SECRET=
DATABASE_URL=

3. Wrangler ​

Führe nach dem Setzen deiner Umgebungsvariablen das folgende Skript aus, um Typen für deine Cloudflare-Workers-Konfiguration zu generieren:

sh
npx wrangler types --env-interface CloudflareBindings
# OR
npm run cf-typegen
sh
pnpm wrangler types --env-interface CloudflareBindings
# OR
pnpm cf-typegen
sh
yarn wrangler types --env-interface CloudflareBindings
# OR
yarn cf-typegen
sh
bunx wrangler types --env-interface CloudflareBindings
# OR
bun run cf-typegen

Stelle anschließend sicher, dass deine tsconfig.json die generierten Typen enthält.

tsconfig.json
json
{
  "compilerOptions": {
    "types": ["worker-configuration.d.ts"]
  }
}

4. Drizzle ​

Um die Drizzle Kit CLI zu verwenden, füge die folgende Drizzle-Konfigurationsdatei im Stammverzeichnis deines Projekts hinzu.

drizzle.config.ts
ts
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  out: './drizzle',
  schema: './src/db/schema.ts',
  dialect: 'postgresql',
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

Anwendung ​

1. Better-Auth-Instanz ​

Erstelle eine Better-Auth-Instanz mit Cloudflare-Workers-Bindings.

Es gibt zahlreiche Konfigurationsoptionen, weit mehr, als dieses Beispiel abdecken kann. Lies die offizielle Dokumentation und passe die Konfiguration an die Anforderungen deines Projekts an:

(Dokumentation: Better Auth – Optionen)

ts
import { neon } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-http';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { betterAuth } from 'better-auth';
import { betterAuthOptions } from './options';

import * as schema from "../db/schema"; // Ensure the schema is imported

/**
 * Better Auth Instance
 */
export const auth = (env: CloudflareBindings): ReturnType<typeof betterAuth> => {
  const sql = neon(env.DATABASE_URL);
  const db = drizzle(sql);

  return betterAuth({
    ...betterAuthOptions,
    database: drizzleAdapter(db, { provider: 'pg' }),
    baseURL: env.BETTER_AUTH_URL,
    secret: env.BETTER_AUTH_SECRET,

    // Additional options that depend on env ...
  });
};
ts
import { BetterAuthOptions } from 'better-auth';

/**
 * Custom options for Better Auth
 *
 * Docs: https://www.better-auth.com/docs/reference/options
 */
export const betterAuthOptions: BetterAuthOptions = {
  /**
   * The name of the application.
   */
  appName: 'YOUR_APP_NAME',
  /**
   * Base path for Better Auth.
   * @default "/api/auth"
   */
  basePath: '/api',

  // .... More options
};

2. Better-Auth-Schema ​

Um die erforderlichen Tabellen für Better Auth zu erstellen, füge zunächst die folgende Datei im Stammverzeichnis hinzu:

better-auth.config.ts
ts
/**
 * Better Auth CLI configuration file
 *
 * Docs: https://www.better-auth.com/docs/concepts/cli
 */
import { neon } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-http';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { betterAuth } from 'better-auth';
import { betterAuthOptions } from './src/lib/better-auth/options';

const { DATABASE_URL, BETTER_AUTH_URL, BETTER_AUTH_SECRET } = process.env;

const sql = neon(DATABASE_URL!);
const db = drizzle(sql);

export const auth: ReturnType<typeof betterAuth> = betterAuth({
  ...betterAuthOptions,
  database: drizzleAdapter(db, { provider: 'pg', schema }),  // schema is required in order for bettter-auth to recognize
  baseURL: BETTER_AUTH_URL,
  secret: BETTER_AUTH_SECRET,
});

Führe dann das folgende Skript aus:

sh
npx @better-auth/cli@latest generate --config ./better-auth.config.ts --output ./src/db/schema.ts
sh
pnpm dlx @better-auth/cli@latest generate --config ./better-auth.config.ts --output ./src/db/schema.ts
sh
yarn dlx @better-auth/cli@latest generate --config ./better-auth.config.ts --output ./src/db/schema.ts
sh
bunx @better-auth/cli@latest generate --config ./better-auth.config.ts --output ./src/db/schema.ts

3. Schema auf die Datenbank anwenden ​

Führe nach dem Generieren der Schemadatei folgende Befehle aus, um die Datenbankmigration zu erstellen und anzuwenden: Prüfe deine Wrangler-Konfiguration, damit process.env korrekt gelesen wird und wrangler dev später funktioniert. Dafür musst du node_compatibility einrichten.

sh
npx drizzle-kit generate
npx drizzle-kit migrate
sh
pnpm drizzle-kit generate
pnpm drizzle-kit migrate
sh
yarn drizzle-kit generate
yarn drizzle-kit migrate
sh
bunx drizzle-kit generate
bunx drizzle-kit migrate

4. Handler einbinden ​

Binde den Better-Auth-Handler an einen Hono-Endpunkt an und stelle sicher, dass der Pfad mit der Einstellung basePath deiner Better-Auth-Instanz übereinstimmt.

src/index.ts
ts
import { Hono } from 'hono';
import { auth } from './lib/better-auth';

const app = new Hono<{ Bindings: CloudflareBindings }>();

app.on(['GET', 'POST'], '/api/*', (c) => {
  return auth(c.env).handler(c.req.raw);
});

export default app;

Fortgeschrittene Verwendung ​

Dieses Beispiel wurde anhand der offiziellen Dokumentation von Hono, Better Auth und Drizzle zusammengestellt. Es geht jedoch über eine einfache Integration hinaus und bietet folgende Vorteile:

  • Effiziente Entwicklung durch die Integration von Cloudflare CLI, Better Auth CLI und Drizzle CLI.
  • Nahtloser Wechsel zwischen Entwicklungs- und Produktionsumgebungen.
  • Konsistentes Anwenden von Änderungen mithilfe eines Skripts.

Du kannst diese Einrichtung mit eigenen Skripten erweitern, die zu deinem Arbeitsablauf passen. Zum Beispiel:

package.json
json
{
  "scripts": {
    "dev": "wrangler dev",
    "deploy": "pnpm run cf-gen-types && wrangler secret bulk .dev.vars.production && wrangler deploy --minify",
    "cf-gen-types": "wrangler types --env-interface CloudflareBindings",
    "better-auth-gen-schema": "pnpm dlx @better-auth/cli@latest generate --config ./better-auth.config.ts --output ./src/db/schema.ts"
  },
}

HINWEIS:
Informationen zur fortgeschrittenen Verwendung und zu aktuellen Optionen findest du in der offiziellen CLI-Dokumentation der jeweiligen Werkzeuge:

Zum Abschluss ​

Du hast jetzt einen leichtgewichtigen, schnellen und umfassenden Authentifizierungsdienst auf Cloudflare Workers. Mit Service Bindings kannst du auf dieser Grundlage mikroservicebasierte Architekturen mit minimaler Latenz aufbauen.

Diese Anleitung zeigt nur ein grundlegendes Beispiel. Für fortgeschrittene Anwendungsfälle wie OAuth oder Rate-Limiting lies die offizielle Dokumentation und passe die Konfiguration an die Anforderungen deines Dienstes an.

Den vollständigen Quellcode des Beispiels findest du hier:
GitHub-Repository

Veröffentlicht unter der MIT-Lizenz.