Fastify Integration for Better Auth
Fastify Better Auth is a Fastify plugin designed to seamlessly integrate the `better-auth` authentication library into Fastify applications. It automates the registration of all necessary authentication routes, typically under `/api/auth/*`, and decorates the Fastify instance with utilities to access the `better-auth` instance and manage session data. The current stable version is 1.2.0, with minor feature releases indicating active development. Key differentiators include its focus on type-safe decorator access to the auth instance via `getAuthDecorator()` and its direct compatibility with Fastify 5.x and Better Auth 1.x, simplifying setup for applications using these specific versions.
Common errors
-
Error: The package 'fastify-better-auth' requires a Node.js version >= 23.10.0. You are using vX.Y.Z.
cause Your Node.js environment is older than the minimum required version 23.10.0.fixUpgrade Node.js to version 23.10.0 or higher (e.g., using `nvm install 23 && nvm use 23`). -
Error: Cannot find module 'better-auth'
cause The peer dependency `better-auth` is not installed or not resolvable by your package manager.fixInstall the `better-auth` package: `npm install better-auth@1.x` or `yarn add better-auth@1.x`. -
FastifyError: FST_ERR_BAD_PLUGIN_OPTS: Plugin 'fastify-better-auth' requires a 'auth' option
cause The `auth` option, which expects an initialized `better-auth` instance, was not provided to the plugin.fixEnsure you pass an `auth` object when registering the plugin: `fastify.register(FastifyBetterAuth, { auth: yourAuthInstance });` -
Property 'getAuthDecorator' does not exist on type 'FastifyInstance<any, any, any, Logger, RawServerDefault>'.
cause You are trying to access `getAuthDecorator` directly on the `fastify` instance, but it's an exported utility function, not a decorator on the instance itself.fixImport `getAuthDecorator` from the package and call it: `import { getAuthDecorator } from 'fastify-better-auth'; const authInstance = getAuthDecorator(fastify);`
Warnings
- breaking This package requires Node.js version 23.10.0 or higher. Running on older Node.js versions will result in installation failures or runtime errors.
- breaking The plugin has strict peer dependency requirements for `fastify@5.x` and `better-auth@1.x`. Incompatible versions of these libraries may lead to runtime errors or unexpected behavior.
- gotcha While module augmentation for TypeScript is possible, `getAuthDecorator()` is the recommended and type-safe way to access the `better-auth` instance from Fastify, especially when plugins extend the auth instance.
Install
-
npm install fastify-better-auth -
yarn add fastify-better-auth -
pnpm add fastify-better-auth
Imports
- FastifyBetterAuth
const FastifyBetterAuth = require('fastify-better-auth');import FastifyBetterAuth from 'fastify-better-auth';
- FastifyBetterAuthOptions
import { FastifyBetterAuthOptions } from 'fastify-better-auth';import { type FastifyBetterAuthOptions } from 'fastify-better-auth'; - getAuthDecorator
const { getAuthDecorator } = require('fastify-better-auth');import { getAuthDecorator } from 'fastify-better-auth';
Quickstart
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import type { FastifyInstance } from 'fastify';
import Fastify from 'fastify';
import FastifyBetterAuth from 'fastify-better-auth';
import fp from 'fastify-plugin';
// Mock DB for demonstration; replace with your actual Drizzle ORM client
const db = {};
// 1. Create the Better Auth instance
export const auth = betterAuth({
trustedOrigins: [process.env.AUTH_URL ?? 'http://localhost:3000'],
database: drizzleAdapter(db as any, { // Cast db to any for mock simplicity
provider: 'pg',
usePlural: true,
}),
emailAndPassword: {
enabled: true,
},
});
// 2. Define and register the plugin using fastify-plugin
async function authPlugin(fastify: FastifyInstance) {
await fastify.register(FastifyBetterAuth, { auth });
fastify.get('/protected', async (request, reply) => {
// Example of accessing the auth instance, though this route is not protected by default
// const authInstance = fastify.getAuthDecorator();
return { message: 'Hello from a route. Auth routes are registered at /api/auth/*' };
});
}
const registeredAuthPlugin = fp(authPlugin, {
name: 'auth-plugin',
});
// 3. Set up and start your Fastify application
const fastify = Fastify({ logger: true });
fastify.register(registeredAuthPlugin);
const start = async () => {
try {
await fastify.listen({ port: 3000 });
console.log('Server listening on http://localhost:3000');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();