Authenticated Routes
Purpose and Scope
Authenticated routes are routes whose UI should only load for a user who has passed an authentication check. In TanStack Router, the primary route-protection tool is route.beforeLoad, a function that runs before a matched route loads. The Router guide frames this as a route guard: useful for navigation control, redirects, and preventing protected UI from loading. It also draws an important security boundary: a route guard is not data authorization. Any Start server function, server route, or external API endpoint that returns private data still needs its own request-time authorization because it can be called independently of the page route that normally reaches it.
Sources: docs/router/guide/authenticated-routes.md, docs/start/framework/react/guide/authentication-overview.md
The recommended mental model is to separate authentication, authorization, and routing. Authentication answers who the user is, while authorization answers what that authenticated user may do. Router route guards are best used to decide whether to enter a route subtree and what redirect should happen when the user is not signed in. Start authentication docs place the secure parts on the server side: session validation, credential checks, token work, database operations, and protected endpoints. The client can manage auth UI and redirect handling, but private data access must be defended at the server boundary.
Sources: docs/start/framework/react/guide/authentication-overview.md, docs/router/guide/authenticated-routes.md
Relevant Source Files
docs/router/guide/authenticated-routes.md- Defines the Router route-guard pattern, thebeforeLoadexecution position, redirect usage, and error handling withisRedirect.docs/start/framework/react/guide/server-routes.md- Explains Start server routes, why they live beside app routes, and why HTTP endpoints used for authentication must authorize requests themselves.docs/start/framework/react/build-from-scratch.md- Shows the Start project shape, thesrc/routesdirectory, generated route tree, and Router configuration used by protected route examples.docs/start/framework/react/comparison.md- Positions Start as the full-stack framework built on TanStack Router, with SSR, server functions, middleware, and deployment capabilities relevant to auth architecture.docs/start/framework/react/getting-started.md- Points readers to auth-capable Start examples such as Basic + Auth, Clerk Auth, Supabase, and WorkOS.docs/start/framework/react/guide/authentication-overview.md- Defines authentication versus authorization, route protection patterns, session approaches, and server-driven auth state guidance.
Core Pattern: Guard a Layout Route
The most scalable Router pattern is to protect a layout route rather than copying checks into every page. A layout route has children and can run beforeLoad before any child route loads. The authenticated-routes guide explicitly notes that parent beforeLoad functions run before child beforeLoad functions, making a guarded parent behave like middleware for the entire subtree. If the parent throws an error or redirect, the child routes do not attempt to load. That ordering lets a route such as /_authenticated centralize the login check for dashboards, account pages, and other private screens.
Sources: docs/router/guide/authenticated-routes.md, docs/start/framework/react/guide/authentication-overview.md
A typical guard redirects anonymous users to /login and stores the attempted URL in search state so the login flow can send them back afterward. The guide recommends using the location argument passed to beforeLoad, specifically location.href, as the source of the current destination. This avoids relying on router.state.resolvedLocation, which can lag behind the actual attempted location. Since redirect() accepts the same options as navigate, the same route-aware navigation contract applies, including options such as replace: true when a login redirect should not add another history entry.
Sources: docs/router/guide/authenticated-routes.md
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/_authenticated')({
beforeLoad: async ({ location }) => {
if (!isAuthenticated()) {
throw redirect({
to: '/login',
search: {
redirect: location.href,
},
})
}
},
})Execution Flow
When a protected URL is requested, Router first matches routes from the top of the tree downward. During matching, route params are parsed and search parameters are validated. Route loading then begins, and route.beforeLoad runs before route.onError, component preload work, and the route loader. This is why auth checks belong in beforeLoad rather than in the route component: the decision happens before the protected component or its child route loaders are allowed to proceed. Preloading follows the same loading pipeline, so guarded branches can also protect speculative navigation work.
Sources: docs/router/guide/authenticated-routes.md
Auth checks often depend on asynchronous session verification. The Router guide shows a defensive pattern for checks that may fail because of network errors, token validation errors, or unavailable identity services. If the auth check intentionally throws a Router redirect, rethrow it using isRedirect(error) so it is not accidentally treated as a failed auth request. For all other failures, redirect to login or to a safe recovery route. This keeps expected navigation redirects distinct from exceptional failures while preserving a predictable route-loading result for users.
Sources: docs/router/guide/authenticated-routes.md
import { createFileRoute, redirect, isRedirect } from '@tanstack/react-router'
export const Route = createFileRoute('/_authenticated')({
beforeLoad: async ({ location }) => {
try {
const user = await verifySession()
if (!user) {
throw redirect({
to: '/login',
search: { redirect: location.href },
})
}
return { user }
} catch (error) {
if (isRedirect(error)) throw error
throw redirect({
to: '/login',
search: { redirect: location.href },
})
}
},
})Start and Server-Side Boundaries
TanStack Start extends the same route tree into a full-stack application model, but it does not turn a client route guard into a security boundary. The Start authentication overview recommends server-driven auth state for security-sensitive applications because the server remains the source of truth and works cleanly with SSR. HTTP-only cookies are called out as the recommended session-management approach for many web applications because they are not accessible to JavaScript and are handled automatically by the browser. JWTs and server-side sessions are also documented options, but each carries different operational and security tradeoffs.
Sources: docs/start/framework/react/guide/authentication-overview.md, docs/start/framework/react/comparison.md
Start server routes are HTTP endpoints defined in ./src/routes alongside app routes by adding a server.handlers object to createFileRoute. The server-routes guide lists authentication as a common use case for these endpoints and explains that they are meant for requests that may come from outside the Start application. That means login callbacks, form submissions, token exchange routes, or private JSON endpoints should validate the incoming request themselves. A user should not gain access to private data merely because a page route would normally have run beforeLoad first.
Sources: docs/start/framework/react/guide/server-routes.md, docs/start/framework/react/guide/authentication-overview.md
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/api/session')({
server: {
handlers: {
GET: async ({ request }) => {
const user = await requireUserFromRequest(request)
return Response.json({ user })
},
},
},
})API Components and Reference
| Component | Where it is used | Auth behavior |
|---|---|---|
createFileRoute('/_authenticated') | File-based Router and Start routes | Defines the protected layout or route entry. |
beforeLoad: async ({ location }) => ... | Route options | Runs before child route loading and can return context or throw. |
redirect({ to, search, replace }) | Router navigation utility | Throws a route-aware redirect, commonly to /login. |
isRedirect(error) | Error handling in auth checks | Distinguishes intentional redirects from failed session checks. |
server.handlers.GET/POST | Start server routes | Handles raw HTTP requests and must authorize private data access. |
The values returned from beforeLoad can be used as route context for downstream code, which makes it a good place to attach an already-verified user object for a protected subtree. Keep that context focused on routing and rendering needs. If a child loader or component needs private data, fetch it through a server primitive or endpoint that checks the session again. This layered approach gives a good user experience, because navigation to private UI is stopped early, and a good security posture, because every private server entry point validates the request on its own.
Sources: docs/router/guide/authenticated-routes.md, docs/start/framework/react/guide/authentication-overview.md, docs/start/framework/react/guide/server-routes.md
Project Setup and Examples
The Start setup docs show that a Start project uses Router as a foundation, with a src/routes directory, a router.tsx configuration file, and a generated routeTree.gen.ts. That structure is where guarded layout routes and login routes live. The getting-started guide also points to working examples that are especially useful for authentication work: start-basic-auth, start-clerk-basic, start-supabase-basic, and start-workos. Those examples are a better next step than designing auth from an abstract API list because they show real login flows, redirect handling, and provider integration in a route tree.
Sources: docs/start/framework/react/build-from-scratch.md, docs/start/framework/react/getting-started.md
Use the Start authentication overview to choose an auth architecture before writing route guards. For many apps, the first implementation should combine HTTP-only cookie sessions, server-driven auth state, a protected layout route, and endpoint-level authorization. For apps using third-party providers, context-based or hybrid state can still work, but the docs caution that synchronization with server state matters. After the basic guard works, test direct requests to server routes and server functions, refreshes on protected URLs, login redirects back to the original location, and failure cases where session verification throws.
Sources: docs/start/framework/react/guide/authentication-overview.md, docs/router/guide/authenticated-routes.md, docs/start/framework/react/guide/server-routes.md
Next Steps
Start by creating a pathless or named layout route for the private section of your app, add a beforeLoad check, and redirect anonymous users with a redirect search parameter based on location.href. Then make the login route consume that search value after a successful login. In a Start app, implement the secure session checks in server functions or server routes, not only in the route guard. Continue with router-context for dependency injection patterns, not-found-errors-and-error-boundaries for thrown route outcomes, and start-server-functions-and-middleware for protecting server-side data access.