@mertdogar/better-auth-do-sqlite
v0.0.25
Published
Complete authentication and database solution for Cloudflare Durable Objects with Better Auth and libSQL HTTP protocol support
Maintainers
Readme
@mertdogar/better-auth-do-sqlite
A Better Auth adapter for Cloudflare Durable Objects with SQLite storage. This library enables you to use Better Auth's authentication features in Cloudflare Workers with Durable Objects as your database layer.
Features
- 🔐 Full Better Auth integration with Cloudflare Durable Objects
- 💾 SQLite storage via Durable Objects
- 🚀 Built for Cloudflare Workers
- 🎯 Type-safe with TypeScript
- 🔄 Session management with Durable Objects
- 🛠️ Works seamlessly with Hono and other frameworks
Installation
npm install @mertdogar/better-auth-do-sqlite better-auth honoOr with other package managers:
# pnpm
pnpm add @mertdogar/better-auth-do-sqlite better-auth hono
# yarn
yarn add @mertdogar/better-auth-do-sqlite better-auth hono
# bun
bun add @mertdogar/better-auth-do-sqlite better-auth honoQuick Start
1. Configure Wrangler
Create or update your wrangler.jsonc:
{
"name": "my-auth-app",
"main": "src/index.ts",
"compatibility_date": "2025-05-04",
"vars": {
"JWT_SECRET": "your-secret-key-here",
},
"durable_objects": {
"bindings": [
{
"class_name": "APPDO",
"name": "APP_DO",
},
],
},
"migrations": [
{
"new_sqlite_classes": ["APPDO"],
"tag": "v1",
},
],
}2. Create Worker Types
Create a worker-configuration.d.ts file:
interface Env extends Cloudflare.Env {
JWT_SECRET: string
APP_DO: DurableObjectNamespace
APP_DO_ID?: string // Optional: defaults to 'app'
}3. Implement Your Worker
import { Hono } from 'hono'
import { AuthDO, authMiddleware, betterAuthRouter, getDO } from '@mertdogar/better-auth-do-sqlite'
// Extend AuthDO to create your Durable Object class
export class APPDO extends AuthDO {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env)
}
}
const app = new Hono<{ Bindings: Env }>()
// Apply auth middleware globally
app.use('*', authMiddleware())
// Mount Better Auth routes
app.route('/api/auth', betterAuthRouter())
// Protected route example
app.get('/', async (c) => {
const appDO = getDO(c, 'app')
const session = await appDO.getActiveSession(c.req.raw)
if (!session) {
return c.json({ error: 'Unauthorized' }, 401)
}
return c.json({ message: 'Hello authenticated user!', session })
})
export default appAPI Reference
AuthDO
The base Durable Object class that provides authentication functionality.
export class APPDO extends AuthDO {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env)
}
}Methods
getActiveSession(request: Request): Promise<Session | null>Retrieves the active session for the given request.
const session = await appDO.getActiveSession(request)
authMiddleware()
Hono middleware that injects session information into the context.
app.use('*', authMiddleware())The middleware reads APP_DO_ID from c.env (defaults to 'app' if not set).
betterAuthRouter<E>()
Hono router that handles all Better Auth endpoints. Generic type parameter allows type-safe integration with your app's environment.
// Basic usage
app.route('/api/auth', betterAuthRouter())
// With explicit types
app.route('/api/auth', betterAuthRouter<{ Bindings: Env }>())The router reads APP_DO_ID from c.env (defaults to 'app' if not set).
betterAuthRouter(bindingPrefix: string)
Hono router that handles all Better Auth endpoints.
Parameters:
bindingPrefix: The prefix of your Durable Object binding (e.g.,'app'forAPP_DO)
app.route('/api/auth', betterAuthRouter('app'))This will create the following endpoints:
POST /api/auth/sign-inPOST /api/auth/sign-upPOST /api/auth/sign-outGET /api/auth/session- And all other Better Auth endpoints
getDO(context: HonoContext, doId: string)
Helper function to get the Durable Object instance.
Parameters:
context: Hono context objectdoId: The Durable Object instance ID/name
const appDO = getDO(c, 'app')sqlServerRouter<E>()
Hono router that proxies libSQL HTTP protocol requests to the Durable Object. Generic type parameter allows type-safe integration.
// Basic usage
app.route('/api/sqld', sqlServerRouter())
// With explicit types
app.route('/api/sqld', sqlServerRouter<{ Bindings: Env }>())The router reads APP_DO_ID and optional prefixRegex from c.env.
Configuration
Environment Variables
Set these in your wrangler.jsonc or .dev.vars file:
# Required
JWT_SECRET=your-secret-key-here-min-32-characters
# Optional - for development
# Add other Better Auth configuration as neededDurable Object Binding
The library expects a Durable Object binding named APP_DO in your wrangler.jsonc. The middleware and routers read APP_DO_ID from c.env to determine which Durable Object instance to use:
// Default behavior: uses instance ID 'app'
app.use('*', authMiddleware())
// Custom instance: set APP_DO_ID dynamically
app.use('/tenant/:id/*', async (c, next) => {
c.env.APP_DO_ID = c.req.param('id')
return authMiddleware()(c, next)
})Advanced Usage
Custom Session Handling
app.get('/profile', async (c) => {
const appDO = getDO(c, 'app')
const session = await appDO.getActiveSession(c.req.raw)
if (!session) {
return c.json({ error: 'Unauthorized' }, 401)
}
// Access user information from session
return c.json({
userId: session.userId,
email: session.user?.email,
// ... other session data
})
})Multiple Authentication Domains
You can use multiple Durable Object instances for different authentication domains by setting different APP_DO_ID values:
// User authentication
export class UserAuthDO extends AuthDO {}
// Admin authentication
export class AdminAuthDO extends AuthDO {}
interface Env {
JWT_SECRET: string
USER_AUTH_DO: DurableObjectNamespace
ADMIN_AUTH_DO: DurableObjectNamespace
APP_DO: DurableObjectNamespace
}
const app = new Hono<{ Bindings: Env }>()
// User routes - set APP_DO_ID to 'userAuth'
app.use('/user/*', async (c, next) => {
c.env.APP_DO_ID = 'userAuth'
return authMiddleware()(c, next)
})
app.route('/user/auth', betterAuthRouter())
// Admin routes - set APP_DO_ID to 'adminAuth'
app.use('/admin/*', async (c, next) => {
c.env.APP_DO_ID = 'adminAuth'
return authMiddleware()(c, next)
})
app.route('/admin/auth', betterAuthRouter())Development
# Install dependencies
npm install
# Start development server
npm run dev
# Deploy to Cloudflare
npm run deployHow It Works
This library leverages Cloudflare Durable Objects with SQLite to provide a serverless, edge-based authentication solution:
- Durable Objects: Each authentication instance runs in a Durable Object, providing strong consistency and SQLite storage
- Better Auth Integration: Full Better Auth functionality is available through the Durable Object interface
- Edge Performance: Authentication runs at the edge, close to your users
- Persistent Storage: SQLite in Durable Objects ensures your authentication data persists
Requirements
- Node.js 16.x or later (or Bun)
- Cloudflare Workers account
- Wrangler CLI (
npm install -g wrangler)
Limitations
- Durable Objects have usage limits that should be considered
- SQLite storage in Durable Objects is persistent per object instance
- Authentication state is isolated per Durable Object instance
Troubleshooting
"Durable Object not found" Error
Make sure your Durable Object binding matches the prefix you're using:
// If using authMiddleware('app')
// Your binding should be APP_DO (uppercase {PREFIX}_DO)Session Not Persisting
Ensure your JWT_SECRET is set and is at least 32 characters long.
TypeScript Errors
Make sure you have the worker types configured:
npm run types # or: wrangler typesContributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details
Related
- Better Auth - The authentication framework
- Cloudflare Durable Objects - Serverless storage and compute
- Hono - Lightweight web framework
