Skip to main content

<ProtectedRoute />

The ProtectedRoute component wraps a route component and enforces authentication. When the user is not signed in it either redirects to a specified URL or renders a fallback element. While authentication state is being resolved it shows a loading state.

note

ProtectedRoute must be rendered inside a ThunderIDProvider. It also requires TanStack Router's router context — wrap your application with RouterProvider.

Usage

Basic Usage

Use ProtectedRoute in the component of a TanStack Router route definition:

src/routes.tsx
import { createRoute } from '@tanstack/react-router'
import { ProtectedRoute } from '@thunderid/tanstack-router'
import Dashboard from './pages/Dashboard'

export const dashboardRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => (
<ProtectedRoute redirectTo="/signin">
<Dashboard />
</ProtectedRoute>
),
})

Custom Fallback

Render a custom element instead of redirecting when the user is not authenticated:

src/routes.tsx
createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => (
<ProtectedRoute
fallback={
<div>
<h2>Sign in required</h2>
<p>You must be signed in to view this page.</p>
</div>
}
>
<Dashboard />
</ProtectedRoute>
),
})

Custom Loading State

Replace the default null loading state with a spinner or skeleton:

src/routes.tsx
createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => (
<ProtectedRoute
redirectTo="/signin"
loader={<div className="spinner">Loading...</div>}
>
<Dashboard />
</ProtectedRoute>
),
})

Protecting a Nested Layout

Protect a group of routes by placing ProtectedRoute in a shared layout route:

src/routes.tsx
import { createRoute, Outlet } from '@tanstack/react-router'
import { ProtectedRoute } from '@thunderid/tanstack-router'

const appLayoutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/app',
component: () => (
<ProtectedRoute redirectTo="/signin">
<Outlet />
</ProtectedRoute>
),
})

const dashboardRoute = createRoute({
getParentRoute: () => appLayoutRoute,
path: '/dashboard',
component: Dashboard,
})

const settingsRoute = createRoute({
getParentRoute: () => appLayoutRoute,
path: '/settings',
component: Settings,
})

Props

PropTypeRequiredDescription
childrenReactElementThe element to render when the user is authenticated
redirectTostringPath to redirect unauthenticated users to. Either redirectTo or fallback must be provided
fallbackReactElementElement to render when the user is not authenticated. Either redirectTo or fallback must be provided
loaderReactNodeElement to render while authentication state is being resolved. Defaults to null
note

You must provide either redirectTo or fallback. If neither is provided, a ThunderIDRuntimeError is thrown.

Differences from @thunderid/react-router

The TanStack Router ProtectedRoute does not include onSignIn or signInOptions props. For custom sign-in logic, use the useThunderID() hook directly in the protected component or layout.

Error Handling

ProtectedRoute throws a ThunderIDRuntimeError if neither redirectTo nor fallback is provided.

// This will throw — one of redirectTo or fallback is required
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© WSO2 LLC. All rights reserved.Privacy PolicyCookie Policy