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"}}
相关推荐
退休倒计时15 小时前
【每日一题】LeetCode 437. 路径总和 III TypeScript
算法·leetcode·typescript
柯克七七20 小时前
给老项目加了 TypeScript,本来只想自己爽,结果全公司代码审查标准被我抬高了
前端·vue.js·typescript
yume_sibai21 小时前
高德地图骑行导航 API 介绍与使用方法
前端·typescript
子兮曰2 天前
TypeScript 7.0 RC 深度解读:Go 重写完成,10 倍提速,编译器的「奇点时刻」
前端·后端·typescript
BAIGAOa2 天前
不止 React:我开源了一个框架无关的终端键盘引擎,Vue/Svelte 都能用
typescript
小蚂蚁i2 天前
把 TypeScript 内置工具类型彻底搞懂,顺便自己封几个好用的
前端·typescript
爸爸6192 天前
07 ArkTS 基础类型与接口定义:从 TypeScript 到鸿蒙的类型升级
javascript·华为·typescript·harmonyos·鸿蒙系统
妙码生花3 天前
从 PHP 到 AI + Golang,程序员自救转型手记(二十六):icon 组件封装
前端·vue.js·typescript
PBitW3 天前
为什么vite中TS报错,可以继续运行?Webpack不行?💡
前端·typescript