Nitro Integration

Integrate Better Auth with Nitro.

Better Auth can be integrated with your Nitro Application (an open source framework to build web servers).

This guide aims to help you integrate Better Auth with your Nitro application in a few simple steps.

Create a new Nitro Application

Start by scaffolding a new Nitro application using the following command:

Terminal
npx create-nitro-app

This will create the nitro-app directory and install all the dependencies. You can now open the nitro-app directory in your code editor.

Prisma Adapter Setup

This guide assumes that you have a basic understanding of Prisma. If you are new to Prisma, you can check out the Prisma documentation.

The sqlite database used in this guide will not work in a production environment. You should replace it with a production-ready database like PostgreSQL.

For this guide, we will be using the Prisma adapter. You can install prisma client by running the following command:

npm install @prisma/client

prisma can be installed as a dev dependency using the following command:

npm install -D prisma

Generate a schema.prisma file in the prisma directory by running the following command:

Terminal
npx prisma init

You can now replace the contents of the schema.prisma file with the following:

prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

// Will be deleted. Just need it to generate the prisma client
model Test {
  id   Int    @id @default(autoincrement())
  name String
}

Ensure that you update the DATABASE_URL in your .env file to point to the location of your database.

.env
DATABASE_URL="file:./dev.db"

Run the following command to generate the Prisma client & sync the database:

Terminal
npx prisma db push

Install & Configure Better Auth

Follow steps 1 & 2 from the installation guide to install Better Auth in your Nitro application & set up the environment variables.

Once that is done, create your Better Auth instance within the server/utils/auth.ts file.

server/utils/auth.ts
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export default betterAuth({
  database: prismaAdapter(prisma, { provider: "sqlite" }),
  emailAndPassword: { enabled: true },
});

Update Prisma Schema

Use the Better Auth CLI to update your Prisma schema with the required models by running the following command:

Terminal
npx auth generate --config server/utils/auth.ts

The --config flag is used to specify the path to the file where you have created your Better Auth instance.

Head over to the prisma/schema.prisma file & save the file to trigger the format on save.

After saving the file, you can run the npx prisma db push command to update the database schema.

Mount The Handler

You can now mount the Better Auth handler in your Nitro application. You can do this by adding the following code to your server/api/auth/[...all].ts file:

server/api/auth/[...all].ts
import auth from "~/server/utils/auth";

export default auth;

This is a catch-all route that will handle all requests to /api/auth/*.

CORS

You can configure CORS for your Nitro app using a route rule in your nitro.config.ts:

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  routeRules: {
    "/api/auth/**": {
      cors: {
        origin: ["http://localhost:3000"],
        credentials: true,
      },
    },
  },
});

If you use cookie-based sessions, set credentials: true and list your frontend's exact origin(s) in origin. A wildcard origin (cors: true) cannot be combined with credentials. If you only use bearer tokens, credentials isn't required. Ensure that the config is in sync with your frontend application.

Learn more about CORS on the Nitro documentation.

Auth Guard/Middleware

You can add an auth guard to your Nitro application to protect routes that require authentication. You can do this by creating a new file server/utils/require-auth.ts and adding the following code:

server/utils/require-auth.ts
import { defineHandler, HTTPError } from "nitro";
import auth from "~/server/utils/auth.ts";

/**
 * Middleware used to require authentication for a route.
 *
 * Can be extended to check for specific roles or permissions.
 */
export default defineHandler(async (event) => {
  const session = await auth.api.getSession({
    headers: event.req.headers,
  });

  if (!session) {
    throw HTTPError.status(401, "Unauthorized");
  }

  // You can save the session to the event context for later use
  event.context.auth = session;
});

You can now use the Object Syntax Event Handler to apply middleware to specific routes:

server/api/secret.get.ts
import { defineHandler } from "nitro";
import requireAuth from "~/server/utils/require-auth.ts";

export default defineHandler({
  middleware: [requireAuth],
  handler: () =>
    Response.json(
      { message: "Secret data" },
      { status: 201, statusText: "Secret data" },
    ),
});

Example

See an example Nitro application integrated with Better Auth & Prisma.