> Discover all available pages from the documentation index: https://mastra.ai/llms.txt # Better Auth The `@mastra/auth-better-auth` package provides authentication for Mastra using Better Auth. It verifies incoming requests using your Better Auth instance and integrates with the Mastra server via the `server.auth` option. ## Prerequisites This example uses Better Auth. Make sure your Better Auth instance is configured and your environment variables are set. ```env # Required by Better Auth BETTER_AUTH_SECRET=... # at least 32 chars BETTER_AUTH_URL=http://localhost:3000 # Example DB URL used by the snippet below (adjust for your setup) DATABASE_URL=postgres://... ``` > **Note:** Better Auth recommends setting `baseURL` explicitly (or via `BETTER_AUTH_URL`) for security and stability. If you haven't mounted Better Auth's handler yet (so your app can sign users in / create sessions), follow the [Better Auth installation guide](https://www.better-auth.com/docs/installation) to mount the `/api/auth/*` route (or your configured base path). ## Installation Install the `@mastra/auth-better-auth` package: **npm**: ```bash npm install @mastra/auth-better-auth ``` **pnpm**: ```bash pnpm add @mastra/auth-better-auth ``` **Yarn**: ```bash yarn add @mastra/auth-better-auth ``` **Bun**: ```bash bun add @mastra/auth-better-auth ``` ## Usage example First, create your Better Auth instance: ```ts import { betterAuth } from 'better-auth' export const auth = betterAuth({ database: { provider: 'postgresql', url: process.env.DATABASE_URL!, }, emailAndPassword: { enabled: true, }, baseURL: process.env.BETTER_AUTH_URL, secret: process.env.BETTER_AUTH_SECRET, }) ``` Then, use it with Mastra: ```ts import { Mastra } from '@mastra/core' import { MastraAuthBetterAuth } from '@mastra/auth-better-auth' import { auth } from '@/lib/auth' const mastraAuth = new MastraAuthBetterAuth({ auth, }) export const mastra = new Mastra({ server: { auth: mastraAuth, }, }) ``` Visit [MastraAuthBetterAuth](https://mastra.ai/reference/auth/better-auth) for all available configuration options. ## Custom authorization ```ts const mastraAuth = new MastraAuthBetterAuth({ auth, async authorizeUser(user) { // Example: only allow verified emails return user?.user?.emailVerified === true }, }) ``` ## Route configuration ```ts const mastraAuth = new MastraAuthBetterAuth({ auth, public: ['/health', '/api/status'], protected: ['/api/*', '/admin/*'], }) ``` ### Matching rules - `public` and `protected` accept exact paths, wildcard patterns (like `/api/*`), and path params (like `/users/:id`). - For method-specific rules, use tuples like `["/api/agents", ["GET", "POST"]]`. - If a route matches both `public` and `protected`, `public` wins and no auth is required. - If neither matches, routes are treated as protected by default (unless a route is explicitly marked `requiresAuth: false`). ## Client-side setup When auth is enabled, requests to Mastra's built-in routes require authentication. In practice, that means your client needs to send whatever credential your Better Auth setup uses for authenticated requests. ### Cookie session (recommended) If your Better Auth setup uses cookies, configure the client to send credentials. For cross-origin requests (e.g. Next.js on `:3000` calling Mastra on `:4111`), enable CORS credentials on the Mastra server: ```ts export const mastra = new Mastra({ server: { auth: mastraAuth, cors: { origin: 'http://localhost:3000', // your frontend origin credentials: true, }, }, }) ``` Then configure the client to include credentials: ```ts import { MastraClient } from '@mastra/client-js' export const mastraClient = new MastraClient({ baseUrl: 'http://localhost:4111', credentials: 'include', }) ``` If you are calling the API directly, include credentials in `fetch` as well: ```ts await fetch('http://localhost:4111/api/agents/weatherAgent/generate', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify({ messages: 'Weather in London' }), }) ``` ### Bearer token You can pass the signed session token as a Bearer token. Retrieve it from your Better Auth client session and include it in the `Authorization` header: ```ts import { MastraClient } from '@mastra/client-js' import { authClient } from './auth-client' // your Better Auth client const session = await authClient.getSession() export const mastraClient = new MastraClient({ baseUrl: 'http://localhost:4111', headers: { Authorization: `Bearer ${session.data?.session.token}`, }, }) ``` Visit [Mastra Client SDK](https://mastra.ai/docs/server/mastra-client) for more configuration options. ### Making authenticated requests **React**: ```tsx import { mastraClient } from '../lib/mastra-client' export const TestAgent = () => { async function handleClick() { const agent = mastraClient.getAgent('weatherAgent') const response = await agent.generate('Weather in London') console.log(response) } return } ``` **cURL**: ```bash curl -X POST http://localhost:4111/api/agents/weatherAgent/generate \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "messages": "Weather in London" }' ``` ## Troubleshooting - **401 on every request**: confirm your Better Auth handler is mounted and your app can create a valid session. Check that your client sends either a session cookie or an `Authorization: Bearer ` header. - **Cookies not sent cross-origin**: set `credentials: "include"` in `MastraClient` and configure `server.cors` with your frontend origin and `credentials: true`. - **Bearer token rejected**: ensure you pass the full signed session token (from `authClient.getSession()`), not a raw or unsigned token. - **Base URL issues**: set `baseURL` in `betterAuth({ ... })` or set `BETTER_AUTH_URL`. - **DB connection errors**: verify `DATABASE_URL` and database provider configuration.