Create a client instance. You can name the file anything you want. Here we are creating client.ts file inside the lib/ directory.
auth-client.ts
import { createAuthClient } from "better-auth/react" // make sure to import from better-auth/reactexport const authClient = createAuthClient({ //you can pass client configuration here})
Once you have created the client, you can use it to sign up, sign in, and perform other actions.
Some of the actions are reactive. The client use nano-store to store the state and re-render the components when the state changes.
The client also uses better-fetch to make the requests. You can pass the fetch configuration to the client.
The api object exported from the auth instance contains all the actions that you can perform on the server. Every endpoint made inside Better Auth is a invocable as a function. Including plugins endpoints.
When you call a function that needs to set cookies, like signInEmail or signUpEmail in a server action, cookies won’t be set. This is because server actions need to use the cookies helper from Next.js to set cookies.
To simplify this, you can use the nextCookies plugin, which will automatically set cookies for you whenever a Set-Cookie header is present in the response.
auth.ts
import { betterAuth } from "better-auth";import { nextCookies } from "better-auth/next-js";export const auth = betterAuth({ //...your config plugins: [nextCookies()] // make sure this is the last plugin in the array})
Now, when you call functions that set cookies, they will be automatically set.
In Next.js middleware, it's recommended to only check for the existence of a session cookie to handle redirection. To avoid blocking requests by making API or database calls.
You can use the getSessionCookie helper from Better Auth for this purpose:
import { NextRequest, NextResponse } from "next/server";import { getSessionCookie } from "better-auth";export async function middleware(request: NextRequest) { const sessionCookie = getSessionCookie(request); // Optionally pass config as the second argument if cookie name or prefix is customized. if (!sessionCookie) { return NextResponse.redirect(new URL("/", request.url)); } return NextResponse.next();}export const config = { matcher: ["/dashboard"], // Specify the routes the middleware applies to};
If you need the full session object, you'll have to fetch it from the /get-session API route. Since Next.js middleware doesn't support running Node.js APIs directly, you must make an HTTP request.
The example uses better-fetch, but you can use any fetch library.
import { betterFetch } from "@better-fetch/fetch";import type { auth } from "@/lib/auth";import { NextRequest, NextResponse } from "next/server";type Session = typeof auth.$Infer.Session;export async function middleware(request: NextRequest) { const { data: session } = await betterFetch<Session>("/api/auth/get-session", { baseURL: request.nextUrl.origin, headers: { cookie: request.headers.get("cookie") || "", // Forward the cookies from the request }, }); if (!session) { return NextResponse.redirect(new URL("/sign-in", request.url)); } return NextResponse.next();}export const config = { matcher: ["/dashboard"], // Apply middleware to specific routes};