TanStack Start has quickly become one of the most talked-about full-stack React frameworks, and until now, wiring up authentication meant hand-rolling OpenID Connect (OIDC) flows or adapting an SDK that was never built for it. That changes with @auth0/auth0-tanstack-start-react, a new SDK purpose-built for TanStack Start's server functions, middleware, and file-based router.
In this post, we will look at what the SDK gives you out of the box, and walk through adding login, logout, and a protected route to a TanStack Start app in a few minutes.
Why a Dedicated SDK
TanStack Start is not Next.js or Remix. It has its own conventions for middleware (createMiddleware), server functions (createServerFn), and route context (beforeLoad). A generic Node OIDC client can get you logged in, but it will not give you typed router context, route guards that plug into beforeLoad, or session helpers that work inside TanStack Start's server functions. The new SDK was built against those primitives directly, so authentication state flows through the router the same way your loader data does.
What You Get
The SDK ships a small, focused API surface:
- Hooks:
useAuth0,useUser,useOrg,useLogin,useLogout,useMfa - Components:
SignedIn,SignedOut,HasOrg,AuthReady,AuthLoading- declarative conditional rendering based on auth state - Route guards:
requireAuthandrequireOrgfor use in a route'sbeforeLoad - Server middleware:
requireAuthMiddleware,withApiAuth,withApiScopes,withApiOrg, and claim-based guards likewithApiClaimIncludes - Server helpers:
getSession(auth0),getAccessToken(auth0),getTokenSet(auth0),createFetcher(auth0)
Auth routes (/auth/login, /auth/callback, /auth/logout, /auth/profile, /auth/backchannel-logout) are mounted automatically once the middleware is registered. There is no route handler file to write yourself.
Setup Auth0 for TanStack Start Apps
Let's see how to set up Auth0 for your StanStack Start application.
Install the Auth0 SDK for Tanstack Start
Execute the following command in your terminal where you have your Tanstack Start React app to install the Auth0 SDK:
npm install @auth0/auth0-tanstack-start-react
Peer dependencies are React 18 or 19, @tanstack/react-router, and @tanstack/react-start v1.
Configure environment variables
Create an Auth0 application (Regular Web App in Auth0 dashboard) and set the following as environment variables:
AUTH0_DOMAIN=YOUR_AUTH0_APP_DOMAIN AUTH0_CLIENT_ID=YOUR_AUTH0_APP_CLIENT_ID AUTH0_CLIENT_SECRET=YOUR_AUTH0_APP_CLIENT_SECRET AUTH0_SECRET=YOUR_LONG_RANDOM_SECRET_HERE APP_BASE_URL=http://localhost:3000
Generate AUTH0_SECRET with openssl rand -hex 32, and set your app's callback URL to http://localhost:3000/auth/callback.
Create the server-side Auth0 instance
Create a server side Auth0 instance to use Auth0 authentication in your TanStack app, as shown in the following code:
// src/auth.server.ts import { auth0Server } from '@auth0/auth0-tanstack-start-react/server'; export const auth0 = auth0Server();
Register the middleware
Register the Auth0 specific middleware in your app to mount auth routes:
// src/start.ts import { createStart } from '@tanstack/react-start'; import { auth0Middleware } from '@auth0/auth0-tanstack-start-react/server/middleware'; export const startInstance = createStart(() => ({ requestMiddleware: [auth0Middleware()], }));
Import from /server/middleware, not the /server barrel, in start.ts. That file runs in both the client and server bundles, and pulling in the full /server module here will break the client build.
Wire up router context and the provider
In the router.tsx file, include auth0RouterContext to access Auth0 router context across routes:
// src/router.tsx import { createRouter as createTanStackRouter } from '@tanstack/react-router'; import { auth0RouterContext } from '@auth0/auth0-tanstack-start-react/client'; import type { Auth0RouterContext } from '@auth0/auth0-tanstack-start-react/types'; import { routeTree } from './routeTree.gen'; export interface RouterContext { auth0: Auth0RouterContext; } export function getRouter() { return createTanStackRouter({ routeTree, context: { auth0: auth0RouterContext } satisfies RouterContext, }); } declare module '@tanstack/react-router' { interface Register { router: ReturnType<typeof getRouter>; } }
Next, update your root route file to wire up the Auth0 router context and wrap your application in the Auth0Provider. This ensures authentication state is properly initialized and available across all routes:
// src/routes/__root.tsx import { createRootRouteWithContext } from '@tanstack/react-router'; import { Auth0Provider, auth0BeforeLoad } from '@auth0/auth0-tanstack-start-react/client'; import type { RouterContext } from '../router'; export const Route = createRootRouteWithContext<RouterContext>()({ beforeLoad: auth0BeforeLoad(), shellComponent: RootDocument, }); function RootDocument({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <Auth0Provider>{children}</Auth0Provider> </body> </html> ); }
Add login and logout
Add login and logout support for your application as shown inn the following examples.
The following code snippet implements a login butto:
// src/components/LoginButton.tsx import { useLogin } from '@auth0/auth0-tanstack-start-react/client'; export function LoginButton() { const login = useLogin(); return <button onClick={() => login('/dashboard')}>Log In</button>; }
Here is the logout button implementation:
// src/components/LogoutButton.tsx import { useLogout } from '@auth0/auth0-tanstack-start-react/client'; export function LogoutButton() { const logout = useLogout(); return <button onClick={() => logout()}>Log Out</button>; }
useLogin and useLogout trigger a full browser navigation rather than a client-side router transition, since the auth routes they hit are handled on the server.
Protect a route
Use requireAuth to protect a route in your app, as shown below:
// src/routes/dashboard.tsx import { createFileRoute } from '@tanstack/react-router'; import { requireAuth, useUser } from '@auth0/auth0-tanstack-start-react/client'; export const Route = createFileRoute('/dashboard')({ beforeLoad: requireAuth({ returnTo: '/dashboard' }), component: Dashboard, }); function Dashboard() { const user = useUser(); return <h1>Welcome, {user?.name}!</h1>; }
requireAuth runs in beforeLoad, that is, before the route's loader or component ever execute. An unauthenticated visitor is redirected to log in and sent back to /dashboard afterward.
Reading the Session on the Server
Server functions and API routes reach the session through the free functions exported from /server, passing your auth0 instance as the first argument:
import { createServerFn } from '@tanstack/react-start'; import { getSession, getAccessToken } from '@auth0/auth0-tanstack-start-react/server'; import { auth0 } from '../auth.server'; const getMyOrders = createServerFn().handler(async () => { const session = await getSession(auth0); const token = await getAccessToken(auth0); // call your API with `token`, scoped to `session.user` });
If you are coming from another Auth0 SDK, note the shape: it is getSession(auth0), not auth0.getSession().
Beyond the Basics
The SDK's examples directory includes a passkeys app alongside the basic OIDC example, showing how to layer WebAuthn-based passwordless login on top of the same session model. Organizations, MFA, and API scope checks (withApiOrg, withApiScopes) are available through the same middleware and guard pattern shown above, so adding them does not mean learning a new mental model, just a new guard.
Try It
The fastest way to see it end to end is the official quickstart, which scaffolds a fresh TanStack Start app and adds the SDK step by step. For the full API surface, including the middleware and server-helper reference, see the SDK README on GitHub.
If you do not already have an Auth0 account yet, create one for free.
About the author

Rengarajan R
Technical Product Manager
