better auth worker on cloudflare

转载于:https://mp.weixin.qq.com/s/li5dsD1kXu6LFMT71bd3AQ

准备工作

  • 创建hono项目
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro cloudflare % npm create hono
> npx
> create-hono
create-hono version 0.19.4

✔ **Target directory** better-auth-cloudflare-demo

✔ **Which template do you want to use?** cloudflare-workers

✔ **Do you want to install project dependencies?** Yes

✔ **Which package manager do you want to use?** npm

✔ Cloning the template

✔ Installing project dependencies

🎉 **Copied project files**

Get started with: **cd better-auth-cloudflare-demo**
  • 安装依赖
shell 复制代码
npm install better-auth 
sql 复制代码
CREATE TABLE IF NOT EXISTS "user" (
	"id" text NOT NULL PRIMARY KEY,
	"name" text NOT NULL,
	"email" text NOT NULL UNIQUE,
	"emailVerified" integer NOT NULL,
	"image" text,
	"createdAt" date NOT NULL,
	"updatedAt" date NOT NULL
);
CREATE TABLE IF NOT EXISTS "session" (
	"id" text NOT NULL PRIMARY KEY,
	"userId" text NOT NULL,
	"token" text NOT NULL UNIQUE,
	"expiresAt" date NOT NULL,
	"ipAddress" text,
	"userAgent" text,
	"createdAt" date NOT NULL,
	"updatedAt" date NOT NULL,
	FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS "account" (
	"id" text NOT NULL PRIMARY KEY,
	"userId" text NOT NULL,
	"accountId" text NOT NULL,
	"providerId" text NOT NULL,
	"accessToken" text,
	"refreshToken" text,
	"accessTokenExpiresAt" date,
	"refreshTokenExpiresAt" date,
	"scope" text,
	"idToken" text,
	"password" text,
	"createdAt" date NOT NULL,
	"updatedAt" date NOT NULL,
	FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS "verification" (
	"id" text NOT NULL PRIMARY KEY,
	"identifier" text NOT NULL,
	"value" text NOT NULL,
	"expiresAt" date NOT NULL,
	"createdAt" date NOT NULL,
	"updatedAt" date NOT NULL
);
	```
* 创建本地数据库
	* 编辑wrangler.jsonc文件,添加d1_databases相关信息,本地运行的时候不存在"database_id",可以将其填为"00000000-0000-0000-0000-000000000000",线上运行的时候,按照真实填写
	```json
	"d1_databases": [  
	  {  
	    "binding": "DB",  
	    "database_name": "better-auth-cloudflare-demo",  
	    "database_id": ""  
	  }  
	]
	```
	* 将上面的sql语句保存在better-auth-cloudflare-demo.sql文件里面并执行如下命令
```shell
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % wrangler d1 execute better-auth-cloudflare-demo --local --file=better-auth-cloudflare-demo.sql
▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.**
 ⛅️ wrangler 4.106.0
────────────────────
**Resource location:** local 
Use --remote if you want to access the remote instance.
🌀 Executing on local database better-auth-cloudflare-demo () from .wrangler/state/v3/d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
🚣 4 commands executed successfully.
	```
	* 查看数据库是否生成成功
		* npx localflare
		* webstrom
		* wrangler
		```shell
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % npx wrangler d1 execute DB --local --command="SELECT name FROM sqlite_master WHERE type='table';"
▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.**
 ⛅️ wrangler 4.110.0
────────────────────
**Resource location:** local 
Use --remote if you want to access the remote instance.
🌀 Executing on local database DB () from .wrangler/state/v3/d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
🚣 1 command executed successfully.
┌──────────────┐
│ name         │
├──────────────┤
│ user         │
├──────────────┤
│ session      │
├──────────────┤
│ account      │
├──────────────┤
│ verification │
├──────────────┤
│ _cf_METADATA
  • 生成worker-configuration.d.ts
shell 复制代码
wrangler types

编写代码

  • src/lib/auth.ts
ts 复制代码
import {betterAuth} from "better-auth"  
  
export const createAuth = (env: Cloudflare.Env)=> betterAuth(  
    {  
        database: env.DB,  
        emailAndPassword: {  
            enabled: true,  
        },  
        secrets: [  
            { version: 1, value: env.SECRET_KEY_V1 },  
        ],  
        basePath: "/api/auth",  
        baseURL: {  
            allowedHosts: [  
                "localhost:*",  
            ],  
            protocol: "auto",  
        },  
    }  
);  
  
export type AuthInstance = ReturnType<typeof createAuth>;  
export type SessionUser = AuthInstance["$Infer"]["Session"]["user"];
  • 创建路由src/routes/user.ts
ts 复制代码
import {Hono} from 'hono'  
import {createAuth, SessionUser} from "../lib/auth";   
export const authRouter = new Hono<{Bindings: Cloudflare.Env, Variables: {user?:SessionUser}}>();  
export const AuthRouterPrefix = "/api/auth";  
// GET/POST /user/auth/*  
authRouter.all("/*", (c) => {  
    const auth = createAuth(c.env);  
    return auth.handler(c.req.raw);  
});  
  
// middleware: /user/*  
authRouter.use("/*", async (c, next) => {  
    const auth = createAuth(c.env);  
    const session = await auth.api.getSession({ headers: c.req.raw.headers });  
    c.set("user", session?.user);  
    await next();  
});  
  
// GET /api/me  
authRouter.get("/me", async (c) => {  
    if (!c.get("user")) {  
        return c.json({ error: "unauthorized" }, 401);  
    }  
    return c.json(c.get("user")!);  
});
  • src/index.ts
ts 复制代码
import { Hono } from 'hono'  
import {createAuth, SessionUser} from "./lib/auth";  
import {authRouter, AuthRouterPrefix} from "./routes/auth"  
  
const app = new Hono<{Bindings: Cloudflare.Env, Variables: {user?:SessionUser}}>()  
  
app.route(AuthRouterPrefix, authRouter);  
  
console.log("=== 当前可用的 API 端点列表 ===");  
app.routes.forEach(r => console.log(`[${r.method}]`.padEnd(8) + r.path));  
console.log("===============================");  
  
export default app

运行和测试

本地

运行

复制代码
```shell
wrangler dev
```

测试

  • 注册
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo %    curl -X POST http://localhost:8787/api/auth/sign-up/email \
    -H 'Content-Type: application/json' \
    -d '{"email":"test@example.com","password":"12345678","name":"test"}'
{"token":"OS57FCQgo9n3maerb7kKoXfD2RNwGBDK","user":{"name":"test","email":"test@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-10T11:10:23.856Z","updatedAt":"2026-07-10T11:10:23.856Z","id":"cvdFAOWgxn6PMd3WD51pMUQoaDW6iw2F"}}
  • 登录
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo %    curl -sS \
    -X POST http://localhost:8787/api/auth/sign-in/email \
    -H 'Content-Type: application/json' \
    -d '{"email":"test@example.com","password":"12345678"}'
{"redirect":false,"token":"Var3ENBaJGZj4VQrpNzwta1cTtbxbUna","user":{"name":"test","email":"test@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-10T11:10:23.856Z","updatedAt":"2026-07-10T11:10:23.856Z","id":"cvdFAOWgxn6PMd3WD51pMUQoaDW6iw2F"}}
  • 错误密码登录
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % curl -sS \
    -X POST http://localhost:8787/api/auth/sign-in/email \
    -H 'Content-Type: application/json' \
    -d '{"email":"test@example.com","password":"password123"}'
{"message":"Invalid email or password","code":"INVALID_EMAIL_OR_PASSWORD"}
  • 不存在的用户登录
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % curl -sS \
    -X POST http://localhost:8787/api/auth/sign-in/email \
    -H 'Content-Type: application/json' \
    -d '{"email":"nobody@example.com","password":"password123"}'
{"message":"Invalid email or password","code":"INVALID_EMAIL_OR_PASSWORD"

cloudflare运行

生成线上数据库

  • 创建数据库
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % wrangler d1 create better-auth-cloudflare-demo
▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.**
 ⛅️ wrangler 4.106.0 (update available 4.110.0)
───────────────────────────────────────────────
✅ Successfully created DB 'better-auth-cloudflare-demo' in region WNAM
Created your new D1 database.
To access your new D1 Database in your Worker, add the following snippet to your configuration file:
{
  "d1_databases": [
    {
      "binding": "better_auth_cloudflare_demo",
      "database_name": "better-auth-cloudflare-demo",
      "database_id": "25b30dd3-b35d-45fa-9fa9-7c2af8240024"
    }
  ]
}
✔ **Would you like Wrangler to add it on your behalf?** ... yes
✔ **What binding name would you like to use?** ... better_auth_cloudflare_demo
✔ **For local dev, do you want to connect to the remote resource instead of a local resource?** ... yes
  • 将返回d1_databases信息,贴到wrangler.jsonc文件对应位置(默认应该会自动更新wrangler.jsonc,无须手动粘贴)
  • 创建表
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % wrangler d1 execute better-auth-cloudflare-demo --remote --file=./better-auth-cloudflare-demo.sql
▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.**
 ⛅️ wrangler 4.106.0 (update available 4.110.0)
───────────────────────────────────────────────
**Resource location:** remote 
✔ **⚠️ This process may take some time, during which your D1 database will be unavailable to serve queries.**
  **Ok to proceed?** ... yes
🌀 Executing on remote database better-auth-cloudflare-demo (25b30dd3-b35d-45fa-9fa9-7c2af8240024):
🌀 To execute on your local development database, remove the --remote flag from your wrangler command.
Note: if the execution fails to complete, your DB will return to its original state and you can safely retry.
├ 🌀 Uploading 25b30dd3-b35d-45fa-9fa9-7c2af8240024.f838ba309bc50ebd.sql
│ 🌀 Uploading complete.
│
🌀 Starting import...
🌀 Processed 4 queries.
🚣 Executed 4 queries in 5.36ms (4 rows read, 14 rows written)
   Database is currently at bookmark 00000001-00000006-000050a4-51499d332507084e452c9586ed6634a2.
┌───────────────────────┬───────────┬──────────────┬───────────────────┐
│Total queries executed │ Rows read │ Rows written │ Database size (MB)│
├───────────────────────┼───────────┼──────────────┼───────────────────┤
│4                      │ 4         │ 14           │ 0.05              │
└───────────────────────┴───────────┴──────────────┴───────────────────┘

发布到线上,也可以使用自己的域名

shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % wrangler deploy
▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.**
 ⛅️ wrangler 4.106.0 (update available 4.110.0)
───────────────────────────────────────────────
Total Upload: 1759.21 KiB / gzip: 304.34 KiB
Worker Startup Time: 47 ms
Your Worker has access to the following bindings:
Binding                                                            Resource        
env.better_auth_cloudflare_demo (better-auth-cloudflare-demo)      D1 Database     
env.BETTER_AUTH_URL ("localhost")                                  Environment Variable      
Uploaded better-auth-cloudflare-demo (5.12 sec)
Deployed better-auth-cloudflare-demo triggers (1.95 sec)
  https://better-auth-cloudflare-demo.shakingwaves.workers.dev
Current Version ID: 2fb6c9de-4448-4954-9209-81ab9402e908
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo % wrangler secret put SECRET_KEY_V1
▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.**
 ⛅️ wrangler 4.106.0 (update available 4.110.0)
───────────────────────────────────────────────
✔ **Enter a secret value:** ... ********************************
🌀 Creating the secret for the Worker "better-auth-cloudflare-demo" 
✨ Success! Uploaded secret SECRET_KEY_V1
  • 测试,以此类推
shell 复制代码
lixiaobo@lixiaobodeMacBook-Pro better-auth-cloudflare-demo %    curl -X POST https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/auth/sign-up/email -H 'Content-Type: application/json' -d '{"email":"test@example.com","password":"12345678","name":"test"}'
{"token":"IBHF3ATPz4akhtFc05AqXgevqpkvq4Vn","user":{"name":"test","email":"test@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-10T12:05:30.596Z","updatedAt":"2026-07-10T12:05:30.596Z","id":"tDVU8UApXsLcm8OZqeXJ6VtH3PZu1ena"}}
 curl -sS -X POST https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/auth/sign-in/email -H 'Content-Type: application/json' -d '{"email":"test@example.com","password":"12345678"}'
{"redirect":false,"token":"nZNqQpSCzDWFwwJ1gCaokeYAgM5uxWOa","user":{"name":"test","email":"test@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-10T12:05:30.596Z","updatedAt":"2026-07-10T12:05:30.596Z","id":"tDVU8UApXsLcm8OZqeXJ6VtH3PZu1ena"}}
相关推荐
东风破_12 小时前
TypeScript 高级类型进阶:keyof、Exclude、Record 与类型组合思想
前端·后端·typescript
晓说前端14 小时前
TypeScript 核心语法应用 —— Vue 3 中的使用(下)
前端·javascript·typescript·类型系统
东风破_16 小时前
(拼多多考题)TypeScript 工具类型:Pick、Omit、Partial、Required
typescript
rimydu1974art18 小时前
opencheck解读:拆解 OpenCheck 的歧视性条款识别与澄清问询机制
人工智能·typescript
触底反弹2 天前
🔥 从「为什么」到「怎么用」:TypeScript 类型约束与泛型完全指南
后端·面试·typescript
Asize2 天前
2 道大厂面试题:TS 工具类型我懂了,CSS 3 列布局把我问住了
前端·css·typescript
电脑玩家柒柒2 天前
DeepSeek Harness 生态观察:插件一夜爆火、标准预设与桌面 Studio,Agent 框架的安卓时刻来了吗
typescript
爱酱丶2 天前
VS Code 快速生成Vue3 + TypeScript + Setup 基础空模板
前端·javascript·typescript
sugar__salt2 天前
三列布局与 TypeScript 工具类型 Pick / Omit / Partial 详解
前端·javascript·typescript
先吃饱再说2 天前
TypeScript 高级工具类型:从“类型世界”到“值世界”,一套组合拳搞定类型转换
typescript