Skip to content
fusion-auth

Sessions

createAuthSession(auth) binds two helpers to your auth instance:

src/lib/auth.ts
export const { getSession, requireSession } = createAuthSession(auth);
  • getSession() → the current session, or null for anonymous users.
  • requireSession() → the session, or a thrown redirect when there is none.

One choke point, two ways to authenticate

There are two ways to be authenticated, and they are resolved in one place so the rest of the app never has to care which was used:

  1. the Better Auth cookie (browsers), or
  2. an Authorization: Bearer sk_live_… API token (scripts, CI, integrations).

Deactivated users (an admin set deactivatedAt) are collapsed to anonymous at this same choke point — so deactivation locks out existing cookies and tokens immediately, with no extra check scattered through the app.

Loading diagram...

Because the token path returns a session-shaped object, callers like requireSession (and an app's requireSiteAdmin) are byte-for-byte identical whether the caller arrived with a cookie or a token.

The resolved shape

Both paths resolve to the same type. The only tell is .session: a cookie session carries the Better Auth session row; a token "session" sets it to null.

async function () {
  const  = await ();
  return ..;
}

Contrast the two return types: getSession() is Session | null (you must handle anonymous), while requireSession() is a non-null Session.

Using them in server functions

getSession — branch on anonymous yourself:

src/routes/dashboard.tsx
import { createServerFn } from "@tanstack/react-start";
import { getSession } from "#/lib/auth";
 
export const loadDashboard = createServerFn().handler(async () => {
  const session = await getSession();
  if (!session) return { signedIn: false as const };
  return { signedIn: true as const, email: session.user.email };
});

requireSession — let it throw. The thrown Response is a 302 to /login, which TanStack Start turns into a redirect:

src/routes/settings.tsx
import { createServerFn } from "@tanstack/react-start";
import { requireSession } from "#/lib/auth";
 
export const loadSettings = createServerFn().handler(async () => {
  const session = await requireSession(); // throws → redirect to /login
  return { email: session.user.email };
});