@airdraft/cloud-auth
v0.1.7
Published
Airdraft Cloud auth adapter interface — pluggable session verification for the cloud dashboard
Downloads
491
Readme
@airdraft/cloud-auth
Pluggable authentication adapter interface for the Airdraft Cloud dashboard. Decouples the cloud handlers from any specific auth library — swap between Better Auth, Clerk, a custom JWT solution, or a mock in tests without changing any business logic.
Installation
npm install @airdraft/cloud-auth
# or
pnpm add @airdraft/cloud-authThe CloudAuthAdapter interface
Every @airdraft/cloud handler accepts a CloudAuthAdapter. Implement this interface to plug in your own auth backend:
import type { CloudAuthAdapter } from '@airdraft/cloud-auth'
const authAdapter: CloudAuthAdapter = {
/**
* Verify the inbound request and return the caller's identity, or null if unauthenticated.
* Typically reads a session cookie or Authorization header.
*/
async verifySession(req: Request): Promise<CloudIdentity | null> { /* ... */ },
/**
* Catch-all HTTP handler for auth routes (login, logout, OAuth callbacks, etc.).
* Mounted at /api/auth/[...all].
*/
async handler(req: Request): Promise<Response> { /* ... */ },
/**
* Programmatically create a user account (used during invite acceptance for new users).
*/
async createUser(input: CreateUserInput): Promise<{ userId: string }> { /* ... */ },
/**
* Delete a user account and all associated sessions.
*/
async deleteUser(userId: string): Promise<void> { /* ... */ },
}CloudIdentity
interface CloudIdentity {
userId: string
email: string
name?: string
avatarUrl?: string
}CreateUserInput
interface CreateUserInput {
email: string
name?: string
password?: string // only required for email/password auth
emailVerified?: boolean // true = skip verification email (e.g. for invited users)
}Default implementation — Better Auth
@airdraft/cloud-auth ships a pre-built adapter for Better Auth:
import { betterAuth } from 'better-auth'
import { admin } from 'better-auth/plugins'
import { mongodbAdapter } from 'better-auth/adapters/mongodb'
import { createBetterAuthAdapter } from '@airdraft/cloud-auth/better-auth'
export const auth = betterAuth({
database: mongodbAdapter(db),
emailAndPassword: { enabled: true },
plugins: [admin()], // required for createUser / deleteUser
secret: process.env.BETTER_AUTH_SECRET!,
})
export const authAdapter = createBetterAuthAdapter(auth)The admin plugin must be enabled for createUser and deleteUser to work. If you don't need programmatic user creation (e.g. invite flow creates users via the auth UI), those methods can be no-ops.
Mounting the handler
// app/api/auth/[...all]/route.ts
import { authAdapter } from '@/lib/auth'
export async function GET(req: Request) { return authAdapter.handler(req) }
export async function POST(req: Request) { return authAdapter.handler(req) }Custom adapter example (Clerk)
import { clerkClient, getAuth } from '@clerk/nextjs/server'
import type { CloudAuthAdapter } from '@airdraft/cloud-auth'
export const authAdapter: CloudAuthAdapter = {
async verifySession(req) {
const { userId } = getAuth(req as any)
if (!userId) return null
const user = await clerkClient.users.getUser(userId)
return { userId, email: user.emailAddresses[0]?.emailAddress ?? '', name: user.fullName ?? undefined }
},
async handler(req) {
// Clerk handles auth via its own middleware — return 404 here
return new Response(null, { status: 404 })
},
async createUser(input) {
const user = await clerkClient.users.createUser({ emailAddress: [input.email], firstName: input.name })
return { userId: user.id }
},
async deleteUser(userId) {
await clerkClient.users.deleteUser(userId)
},
}Test mock
import type { CloudAuthAdapter } from '@airdraft/cloud-auth'
export function createMockAuthAdapter(identity: { userId: string; email: string } | null): CloudAuthAdapter {
return {
async verifySession() { return identity },
async handler() { return new Response(null, { status: 404 }) },
async createUser(i) { return { userId: 'mock-' + i.email } },
async deleteUser() { },
}
}Exports
import type { CloudAuthAdapter, CloudIdentity, CreateUserInput } from '@airdraft/cloud-auth'
import { createBetterAuthAdapter } from '@airdraft/cloud-auth/better-auth'