From 186169048b197947aa2c01e69c441dd568ab3bce Mon Sep 17 00:00:00 2001 From: Yogesh Chaudhary Date: Thu, 17 Sep 2026 08:16:50 +0530 Subject: [PATCH 1/3] docs: add React Router quickstart and SDK library entry --- main/config/navigation/quickstarts.json | 1 + main/docs/images/icons/dark/react-router.svg | 14 + main/docs/images/icons/light/react-router.svg | 14 + main/docs/libraries.mdx | 1 + main/docs/quickstart/webapp/react-router.mdx | 419 ++++++++++++++++++ main/docs/quickstarts.mdx | 11 + main/snippets/sdks/versions.mdx | 17 + 7 files changed, 477 insertions(+) create mode 100644 main/docs/images/icons/dark/react-router.svg create mode 100644 main/docs/images/icons/light/react-router.svg create mode 100644 main/docs/quickstart/webapp/react-router.mdx diff --git a/main/config/navigation/quickstarts.json b/main/config/navigation/quickstarts.json index c94c05b01a..b45a988344 100644 --- a/main/config/navigation/quickstarts.json +++ b/main/config/navigation/quickstarts.json @@ -18,6 +18,7 @@ "pages": [ "docs/quickstart/webapp/nextjs", "docs/quickstart/webapp/tanstack-start", + "docs/quickstart/webapp/react-router", "docs/quickstart/webapp/nuxt", "docs/quickstart/webapp/express", "docs/quickstart/webapp/express-beta", diff --git a/main/docs/images/icons/dark/react-router.svg b/main/docs/images/icons/dark/react-router.svg new file mode 100644 index 0000000000..911c8f6d8e --- /dev/null +++ b/main/docs/images/icons/dark/react-router.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/main/docs/images/icons/light/react-router.svg b/main/docs/images/icons/light/react-router.svg new file mode 100644 index 0000000000..30cee1849b --- /dev/null +++ b/main/docs/images/icons/light/react-router.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/main/docs/libraries.mdx b/main/docs/libraries.mdx index 042b41d5f0..faaf50d87a 100644 --- a/main/docs/libraries.mdx +++ b/main/docs/libraries.mdx @@ -26,6 +26,7 @@ Have a traditional web application that runs on a server? Auth0 maintains these + diff --git a/main/docs/quickstart/webapp/react-router.mdx b/main/docs/quickstart/webapp/react-router.mdx new file mode 100644 index 0000000000..aea80e60b7 --- /dev/null +++ b/main/docs/quickstart/webapp/react-router.mdx @@ -0,0 +1,419 @@ +--- +title: Add Login to Your React Router Application +sidebarTitle: React Router +description: This guide demonstrates how to integrate Auth0 with a React Router v7 application using the Auth0 React Router SDK. +mode: wide +validatedOn: 2026-09-17 +--- + +import {AuthCodeBlock} from "/snippets/AuthCodeBlock.jsx"; +import {CreateInteractiveApp} from "/snippets/recipe.jsx"; +import {HowToSchema} from "/snippets/HowToSchema.jsx"; + + + + + **Prerequisites:** Before you begin, ensure you have the following installed: + + - **[Node.js](https://nodejs.org/en/download)** 18 or newer (20 LTS recommended) + - **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 9+, **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+, or **[pnpm](https://pnpm.io/installation)** 8+ + - React Router v7 or later (framework mode — `react-router.config.ts` present) + + Verify installation: `node --version && npm --version` + + + + `@auth0/auth0-react-router` is currently in **beta** (`1.0.0-beta.2`). The API may change before the stable 1.0 release. + + +## Get Started + +Add Auth0 login and logout to a React Router application. The SDK handles the OIDC flow server-side and stores the session in a JWE-encrypted cookie — tokens never reach the browser. + + + +Use the following prompt with your AI coding tool (Cursor, Copilot, Claude Code, etc.) to integrate Auth0 into your application: + +> Add Auth0 authentication to my React Router app. Use the @auth0/auth0-react-router SDK. +> Follow the Auth0 React Router quickstart: https://auth0.com/docs/quickstart/webapp/react-router/interactive + +Or install the Auth0 agent skills directly: + +```shell +npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-react-router +``` + +This will automatically: +- Create an Auth0 application in your dashboard +- Fetch your credentials +- Configure the Auth0 provider in your app +- Add login, logout, and user profile components + + + +export const envSnippet = `AUTH0_DOMAIN={yourDomain} +AUTH0_CLIENT_ID={yourClientId} +AUTH0_CLIENT_SECRET={yourClientSecret} +AUTH0_SESSION_SECRET={yourSessionSecret} +AUTH0_APP_BASE_URL=http://localhost:5173`; + + + +## Create a new React Router project + +```shell +npx create-react-router@latest my-app +cd my-app +npm install +``` + +This scaffolds a React Router framework-mode project with Vite. The dev server runs on `http://localhost:5173`. + + +Skip this step if you are adding Auth0 to an existing React Router app. + + +## Install @auth0/auth0-react-router + +```shell +npm install @auth0/auth0-react-router +``` + +## Configure Auth0 + +Create an Auth0 application and set the callback and logout URLs. + + + + + + + + + +```shell +auth0 apps create \ + --name "React Router App" \ + --type regular_web \ + --callbacks http://localhost:5173/auth/callback \ + --logout-urls http://localhost:5173 +``` + + + + +1. Go to [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > Applications** +2. Click **Create Application**, enter a name, and select **Regular Web Application** +3. Click **Create** +4. Open the **Settings** tab (Application Settings) +5. Set the following fields: + +| Field | Value | +|-------|-------| +| Allowed Callback URLs | `http://localhost:5173/auth/callback` | +| Allowed Logout URLs | `http://localhost:5173` | + +6. Click **Save Changes** +7. Copy **Domain** and **Client ID** from Application Settings — you will use them in the next step + + + + +## Configure environment variables + +Create a `.env` file at the root of your project: + + + +| Variable | Where to find it | +|----------|-----------------| +| `AUTH0_DOMAIN` | Application Settings → Domain | +| `AUTH0_CLIENT_ID` | Application Settings → Client ID | +| `AUTH0_CLIENT_SECRET` | Application Settings → Client Secret | +| `AUTH0_SESSION_SECRET` | A random 32+ character string — run `openssl rand -hex 32` to generate one | +| `AUTH0_APP_BASE_URL` | Your app's base URL — `http://localhost:5173` for local development | + + +Never commit `.env` to version control. Add it to `.gitignore` before your first commit. + + +## Create the Auth0 server instance + +Create `app/auth0.server.ts`. The `.server.ts` suffix tells React Router's bundler to exclude this file from the client bundle, keeping your secrets server-only. + +```ts app/auth0.server.ts +import { Auth0Server, registerAuth0Instance } from '@auth0/auth0-react-router/server'; + +// Reads AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, +// AUTH0_SESSION_SECRET, and AUTH0_APP_BASE_URL from environment variables +export const auth0 = new Auth0Server(); + +// Wires the instance to standalone helpers (getSession, updateSession, etc.) +// so that hooks like onCallback and beforeSessionSaved fire everywhere +registerAuth0Instance(auth0); +``` + +## Add the auth routes + +Create a splat route that handles all `/auth/*` paths. `handleAuth` dispatches internally to `handleLogin`, `handleCallback`, `handleLogout`, and `handleBackchannelLogout` based on the URL path and HTTP method. + +```tsx app/routes/auth.$.tsx +import { handleAuth } from '@auth0/auth0-react-router/server'; +import { auth0 } from '../auth0.server'; + +export const loader = ({ request }: { request: Request }) => + handleAuth(auth0, request); + +export const action = ({ request }: { request: Request }) => + handleAuth(auth0, request); +``` + +Register the route in your route config: + +```ts app/routes.ts +import { type RouteConfig, route } from '@react-router/dev/routes'; + +export default [ + route('auth/*', 'routes/auth.$.tsx'), + // ... your other routes +] satisfies RouteConfig; +``` + +## Configure the root layout + +Add `Auth0Provider` and `rootAuthLoader` to `app/root.tsx`. `rootAuthLoader` decrypts the session cookie and passes the auth state to the provider — no tokens are sent to the browser. + +```tsx app/root.tsx expandable +import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router'; +import { Auth0Provider } from '@auth0/auth0-react-router'; +import { rootAuthLoader } from '@auth0/auth0-react-router/server'; +import type { Route } from './+types/root'; + +export const loader = ({ request }: Route.LoaderArgs) => + rootAuthLoader(request); + +export default function Root() { + return ( + + + + + + + + + + + + + + + + ); +} +``` + + +`Auth0Provider` reads session data from `useRouteLoaderData('root')`, so the root route must have the id `root`. With file-based routing React Router sets this from the filename automatically. With a custom route config, pass `{ id: 'root' }` to the `layout()` call. + + +## Add login and logout + +Use the built-in components to show login and logout controls. `LoginButton` redirects to `/auth/login` and `LogoutButton` redirects to `/auth/logout`. Auth0 handles the OIDC flow and redirects the user back to your app after sign-in. + +```tsx app/routes/_index.tsx +import { + AuthLoading, + LoginButton, + LogoutButton, + SignedIn, + SignedOut, +} from '@auth0/auth0-react-router'; + +export default function Home() { + return ( +
+

Welcome

+ +

Loading…

+
+ + Log in + + + Log out + +
+ ); +} +``` + +## Show the user profile + +Use the `useUser` hook to access the authenticated user's profile in any client component. Pair it with `requireSession` in the loader to block unauthenticated requests at the server before the page renders. + +```tsx app/routes/profile.tsx +import { useUser } from '@auth0/auth0-react-router'; +import { requireSession } from '@auth0/auth0-react-router/server'; +import type { Route } from './+types/profile'; + +// Server-side guard — redirects to /auth/login if the user is not authenticated +export const loader = async ({ request }: Route.LoaderArgs) => { + await requireSession(request); + return null; +}; + +export default function Profile() { + const user = useUser(); + + return ( +
+

Profile

+ {user && ( +
+ {user.name +

+ {user.name} +

+

{user.email}

+
+ )} +
+ ); +} +``` + +## Run your application + +```shell +npm run dev +``` + +Open `http://localhost:5173` in your browser and click **Log in**. You will be redirected to the Auth0 Universal Login page. After signing in you will be redirected back to your app. + + +Your app now has working login and logout. The session is stored in a JWE-encrypted cookie — access tokens stay on the server and are never sent to the browser. + + +
+ +## Troubleshooting + + + + + +**Cause:** `AUTH0_SESSION_SECRET` changed after a session cookie was issued, or the value is fewer than 32 characters. + +**Fix:** Clear your browser cookies for `localhost`, confirm `AUTH0_SESSION_SECRET` is at least 32 characters, and restart the dev server. To generate a new secret: `openssl rand -hex 32`. + + + + + +**Cause:** The redirect URL Auth0 receives does not match any value in Allowed Callback URLs. + +**Fix:** In [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > Applications** → select your app → **Application Settings**, confirm **Allowed Callback URLs** is set to `http://localhost:5173/auth/callback`. Remove any trailing slashes or extra whitespace, then click **Save Changes**. + + + + + +**Cause:** The `auth.$.tsx` splat route is missing or not registered in `routes.ts`. + +**Fix:** Confirm `app/routes/auth.$.tsx` exists and that `app/routes.ts` includes `route('auth/*', 'routes/auth.$.tsx')`. Restart the dev server after editing `routes.ts`. + + + + + +**Cause:** `rootAuthLoader` is not exported from `app/root.tsx`, or the root route does not have the id `root`. + +**Fix:** Confirm `app/root.tsx` exports `export const loader = ({ request }) => rootAuthLoader(request)`. With a custom route config, register the root layout as `layout('root.tsx', { id: 'root' }, [...routes])`. + + + + + +**Cause:** `defineRouteAuth` and `auth0Middleware` require React Router 7.9.0 or later, which introduced the middleware API. + +**Fix:** Upgrade `react-router` to `>=7.9.0`, or protect routes individually using `requireSession` / `requireUser` in each loader instead. + + + + + +## Advanced Usage + + + + + +Add `AUTH0_AUDIENCE` to `.env` with your API's identifier (from [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > APIs** → **API Settings → Identifier**). Then use `getAccessToken` in a loader — the token never reaches the browser: + +```ts app/routes/data.tsx +import { getAccessToken } from '@auth0/auth0-react-router/server'; +import { TokenError } from '@auth0/auth0-react-router/errors'; + +export const loader = async ({ request }) => { + let token: string; + try { + token = await getAccessToken(request); + } catch (err) { + if (err instanceof TokenError) { + return new Response(null, { status: 302, headers: { Location: '/auth/login' } }); + } + throw err; + } + const data = await fetch('https://api.example.com/items', { + headers: { Authorization: `Bearer ${token}` }, + }).then(r => r.json()); + return { data }; +}; +``` + + + + + +Use `defineRouteAuth` middleware (React Router ≥ 7.9.0) to enforce roles at the route level. Roles are read from the `https://auth0.com/claims/roles` claim by default: + +```ts app/routes/admin.tsx +import { defineRouteHandle } from '@auth0/auth0-react-router'; +import { defineRouteAuth, auth0UserContext } from '@auth0/auth0-react-router/server'; + +export const handle = defineRouteHandle({ role: 'admin' }); + +export const middleware = defineRouteAuth({ role: 'admin' }).middleware; + +export const loader = ({ context }) => { + const user = context.get(auth0UserContext); + return { user }; +}; +``` + +Requests without the required role receive a `403`. + + + + + +The SDK can run in a purely client-side mode backed by `@auth0/auth0-spa-js`. Add `VITE_AUTH0_DOMAIN` and `VITE_AUTH0_CLIENT_ID` to your `.env` — `Auth0Provider` detects these automatically and switches to the PKCE flow. No other code changes are required. + +```shell +# .env additions for SPA mode +VITE_AUTH0_DOMAIN={yourDomain} +VITE_AUTH0_CLIENT_ID={yourClientId} +``` + + +Do not set both `AUTH0_*` and `VITE_AUTH0_*` variables at the same time. Hybrid mode is not supported — when both are present, SPA logout will not clear the server-side session cookie. + + + + + diff --git a/main/docs/quickstarts.mdx b/main/docs/quickstarts.mdx index 7b1ec2482a..752427a8bc 100644 --- a/main/docs/quickstarts.mdx +++ b/main/docs/quickstarts.mdx @@ -178,6 +178,17 @@ Traditional web app that runs on the server }} /> + + Date: Thu, 17 Sep 2026 15:30:28 +0530 Subject: [PATCH 2/3] fix: use v7+ phrasing for React Router version --- main/docs/quickstart/webapp/react-router.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/docs/quickstart/webapp/react-router.mdx b/main/docs/quickstart/webapp/react-router.mdx index aea80e60b7..139505bb3f 100644 --- a/main/docs/quickstart/webapp/react-router.mdx +++ b/main/docs/quickstart/webapp/react-router.mdx @@ -1,7 +1,7 @@ --- title: Add Login to Your React Router Application sidebarTitle: React Router -description: This guide demonstrates how to integrate Auth0 with a React Router v7 application using the Auth0 React Router SDK. +description: This guide demonstrates how to integrate Auth0 with a React Router application (framework mode, v7 or later) using the Auth0 React Router SDK. mode: wide validatedOn: 2026-09-17 --- @@ -17,7 +17,7 @@ import {HowToSchema} from "/snippets/HowToSchema.jsx"; - **[Node.js](https://nodejs.org/en/download)** 18 or newer (20 LTS recommended) - **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 9+, **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+, or **[pnpm](https://pnpm.io/installation)** 8+ - - React Router v7 or later (framework mode — `react-router.config.ts` present) + - React Router framework mode, v7 or later (`react-router.config.ts` present) Verify installation: `node --version && npm --version` From 52e8df510d0c7b03018dced4d081ed6bd004b411 Mon Sep 17 00:00:00 2001 From: Yogesh Chaudhary Date: Thu, 17 Sep 2026 23:15:39 +0530 Subject: [PATCH 3/3] fix: update react-router quickstart to match current docs-v2 format --- main/docs/quickstart/webapp/react-router.mdx | 537 ++++++++++--------- 1 file changed, 273 insertions(+), 264 deletions(-) diff --git a/main/docs/quickstart/webapp/react-router.mdx b/main/docs/quickstart/webapp/react-router.mdx index 139505bb3f..52afad9077 100644 --- a/main/docs/quickstart/webapp/react-router.mdx +++ b/main/docs/quickstart/webapp/react-router.mdx @@ -12,295 +12,304 @@ import {HowToSchema} from "/snippets/HowToSchema.jsx"; - - **Prerequisites:** Before you begin, ensure you have the following installed: - - - **[Node.js](https://nodejs.org/en/download)** 18 or newer (20 LTS recommended) - - **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 9+, **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+, or **[pnpm](https://pnpm.io/installation)** 8+ - - React Router framework mode, v7 or later (`react-router.config.ts` present) - - Verify installation: `node --version && npm --version` - - `@auth0/auth0-react-router` is currently in **beta** (`1.0.0-beta.2`). The API may change before the stable 1.0 release. -## Get Started - -Add Auth0 login and logout to a React Router application. The SDK handles the OIDC flow server-side and stores the session in a JWE-encrypted cookie — tokens never reach the browser. - - + +If you use an AI coding assistant like Claude Code, Cursor, or GitHub Copilot, you can add Auth0 authentication automatically in minutes using [agent skills](https://agentskills.io/home). -Use the following prompt with your AI coding tool (Cursor, Copilot, Claude Code, etc.) to integrate Auth0 into your application: +**Install:** -> Add Auth0 authentication to my React Router app. Use the @auth0/auth0-react-router SDK. -> Follow the Auth0 React Router quickstart: https://auth0.com/docs/quickstart/webapp/react-router/interactive - -Or install the Auth0 agent skills directly: - -```shell -npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-react-router +```bash +npx skills add auth0/agent-skills --skill auth0 ``` -This will automatically: -- Create an Auth0 application in your dashboard -- Fetch your credentials -- Configure the Auth0 provider in your app -- Add login, logout, and user profile components - - - -export const envSnippet = `AUTH0_DOMAIN={yourDomain} -AUTH0_CLIENT_ID={yourClientId} -AUTH0_CLIENT_SECRET={yourClientSecret} -AUTH0_SESSION_SECRET={yourSessionSecret} -AUTH0_APP_BASE_URL=http://localhost:5173`; - - +**Then ask your AI assistant:** -## Create a new React Router project - -```shell -npx create-react-router@latest my-app -cd my-app -npm install -``` - -This scaffolds a React Router framework-mode project with Vite. The dev server runs on `http://localhost:5173`. - - -Skip this step if you are adding Auth0 to an existing React Router app. - - -## Install @auth0/auth0-react-router - -```shell -npm install @auth0/auth0-react-router -``` - -## Configure Auth0 - -Create an Auth0 application and set the callback and logout URLs. - - - - - - - - - -```shell -auth0 apps create \ - --name "React Router App" \ - --type regular_web \ - --callbacks http://localhost:5173/auth/callback \ - --logout-urls http://localhost:5173 +```text +Add Auth0 authentication to my React Router app ``` - - - -1. Go to [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > Applications** -2. Click **Create Application**, enter a name, and select **Regular Web Application** -3. Click **Create** -4. Open the **Settings** tab (Application Settings) -5. Set the following fields: - -| Field | Value | -|-------|-------| -| Allowed Callback URLs | `http://localhost:5173/auth/callback` | -| Allowed Logout URLs | `http://localhost:5173` | - -6. Click **Save Changes** -7. Copy **Domain** and **Client ID** from Application Settings — you will use them in the next step - - - - -## Configure environment variables - -Create a `.env` file at the root of your project: - - - -| Variable | Where to find it | -|----------|-----------------| -| `AUTH0_DOMAIN` | Application Settings → Domain | -| `AUTH0_CLIENT_ID` | Application Settings → Client ID | -| `AUTH0_CLIENT_SECRET` | Application Settings → Client Secret | -| `AUTH0_SESSION_SECRET` | A random 32+ character string — run `openssl rand -hex 32` to generate one | -| `AUTH0_APP_BASE_URL` | Your app's base URL — `http://localhost:5173` for local development | - - -Never commit `.env` to version control. Add it to `.gitignore` before your first commit. - - -## Create the Auth0 server instance - -Create `app/auth0.server.ts`. The `.server.ts` suffix tells React Router's bundler to exclude this file from the client bundle, keeping your secrets server-only. - -```ts app/auth0.server.ts -import { Auth0Server, registerAuth0Instance } from '@auth0/auth0-react-router/server'; - -// Reads AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, -// AUTH0_SESSION_SECRET, and AUTH0_APP_BASE_URL from environment variables -export const auth0 = new Auth0Server(); - -// Wires the instance to standalone helpers (getSession, updateSession, etc.) -// so that hooks like onCallback and beforeSessionSaved fire everywhere -registerAuth0Instance(auth0); -``` - -## Add the auth routes - -Create a splat route that handles all `/auth/*` paths. `handleAuth` dispatches internally to `handleLogin`, `handleCallback`, `handleLogout`, and `handleBackchannelLogout` based on the URL path and HTTP method. - -```tsx app/routes/auth.$.tsx -import { handleAuth } from '@auth0/auth0-react-router/server'; -import { auth0 } from '../auth0.server'; - -export const loader = ({ request }: { request: Request }) => - handleAuth(auth0, request); +Your AI assistant will automatically create your Auth0 application, fetch credentials, install `@auth0/auth0-react-router`, configure the provider, and set up your routes. [Full agent skills documentation →](/docs/quickstart/agent-skills) + -export const action = ({ request }: { request: Request }) => - handleAuth(auth0, request); -``` + + **Prerequisites:** Before you begin, ensure you have the following installed: -Register the route in your route config: + - **[Node.js](https://nodejs.org/en/download)** 18 or newer (20 LTS recommended) + - **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 9+, **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22+, or **[pnpm](https://pnpm.io/installation)** 8+ + - **[jq](https://jqlang.org/)** - Required for Auth0 CLI setup + - React Router framework mode, v7 or later (`react-router.config.ts` present) + -```ts app/routes.ts -import { type RouteConfig, route } from '@react-router/dev/routes'; -export default [ - route('auth/*', 'routes/auth.$.tsx'), - // ... your other routes -] satisfies RouteConfig; -``` +## Get Started -## Configure the root layout - -Add `Auth0Provider` and `rootAuthLoader` to `app/root.tsx`. `rootAuthLoader` decrypts the session cookie and passes the auth state to the provider — no tokens are sent to the browser. - -```tsx app/root.tsx expandable -import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router'; -import { Auth0Provider } from '@auth0/auth0-react-router'; -import { rootAuthLoader } from '@auth0/auth0-react-router/server'; -import type { Route } from './+types/root'; - -export const loader = ({ request }: Route.LoaderArgs) => - rootAuthLoader(request); - -export default function Root() { - return ( - - - - - - - - - - - - - - - - ); -} -``` +This quickstart demonstrates how to add Auth0 authentication to a React Router application. You'll build a secure app with login, logout, and user profile features using the Auth0 React Router SDK. The SDK handles the OIDC flow server-side and stores the session in a JWE-encrypted cookie — tokens never reach the browser. - -`Auth0Provider` reads session data from `useRouteLoaderData('root')`, so the root route must have the id `root`. With file-based routing React Router sets this from the filename automatically. With a custom route config, pass `{ id: 'root' }` to the `layout()` call. - - -## Add login and logout - -Use the built-in components to show login and logout controls. `LoginButton` redirects to `/auth/login` and `LogoutButton` redirects to `/auth/logout`. Auth0 handles the OIDC flow and redirects the user back to your app after sign-in. - -```tsx app/routes/_index.tsx -import { - AuthLoading, - LoginButton, - LogoutButton, - SignedIn, - SignedOut, -} from '@auth0/auth0-react-router'; - -export default function Home() { - return ( -
-

Welcome

- -

Loading…

-
- - Log in - - - Log out - -
- ); +export function generateRandomString(length) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + return Array.from({length}, () => chars[Math.floor(Math.random() * chars.length)]).join(''); } -``` - -## Show the user profile - -Use the `useUser` hook to access the authenticated user's profile in any client component. Pair it with `requireSession` in the loader to block unauthenticated requests at the server before the page renders. - -```tsx app/routes/profile.tsx -import { useUser } from '@auth0/auth0-react-router'; -import { requireSession } from '@auth0/auth0-react-router/server'; -import type { Route } from './+types/profile'; -// Server-side guard — redirects to /auth/login if the user is not authenticated -export const loader = async ({ request }: Route.LoaderArgs) => { - await requireSession(request); - return null; -}; - -export default function Profile() { - const user = useUser(); - - return ( -
-

Profile

- {user && ( -
- {user.name -

- {user.name} -

-

{user.email}

-
- )} -
- ); -} -``` +export const envSnippet = `AUTH0_DOMAIN={yourDomain} +AUTH0_CLIENT_ID={yourClientId} +AUTH0_CLIENT_SECRET={yourClientSecret} +AUTH0_SESSION_SECRET=${generateRandomString(32)} +AUTH0_APP_BASE_URL=http://localhost:5173`; -## Run your application + + + Create a new React Router project for this Quickstart: + + ```shellscript + npx create-react-router@latest my-app + ``` + + Open the project: + + ```shellscript + cd my-app && npm install + ``` + + + Skip this step if you are adding Auth0 to an existing React Router app. + + + + + ```shellscript + npm install @auth0/auth0-react-router + ``` + + + + Create an Auth0 application and set the callback and logout URLs. + + + + + + + + Run the following command from your project's root directory to create an Auth0 app and generate a `.env` file: + + + ```shellscript Mac + # Install Auth0 CLI (if not already installed) + brew tap auth0/auth0-cli && brew install auth0 + + # Set up Auth0 app and generate .env file + auth0 qs setup --app --type regular --framework react-router --port 5173 --name "My React Router App" + ``` + + ```powershell Windows + # Install Auth0 CLI (if not already installed) + scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git + scoop install auth0 + + # Set up Auth0 app and generate .env file + auth0 qs setup --app --type regular --framework react-router --port 5173 --name "My React Router App" + ``` + + + + This command will create an Auth0 Regular Web Application configured for `http://localhost:5173` and generate a `.env` file with all required credentials. Skip step 4 if you use this option. + + + + + 1. Go to [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > Applications** + 2. Click **Create Application**, enter a name, and select **Regular Web Application** + 3. Click **Create** + 4. Open the **Settings** tab (Application Settings) + 5. Set the following fields: + + | Field | Value | + |-------|-------| + | Allowed Callback URLs | `http://localhost:5173/auth/callback` | + | Allowed Logout URLs | `http://localhost:5173` | + + 6. Click **Save Changes** + 7. Copy **Domain** and **Client ID** from Application Settings — you will use them in the next step + + + + + + Create a `.env` file at the root of your project: + + + + | Variable | Where to find it | + |----------|-----------------| + | `AUTH0_DOMAIN` | Application Settings → Domain | + | `AUTH0_CLIENT_ID` | Application Settings → Client ID | + | `AUTH0_CLIENT_SECRET` | Application Settings → Client Secret | + | `AUTH0_SESSION_SECRET` | A random 32+ character string — auto-generated in the snippet above | + | `AUTH0_APP_BASE_URL` | Your app's base URL — `http://localhost:5173` for local development | + + + Never commit `.env` to version control. Add it to `.gitignore` before your first commit. + + + + + Create `app/auth0.server.ts`. The `.server.ts` suffix tells React Router's bundler to exclude this file from the client bundle, keeping your secrets server-only. + + ```ts app/auth0.server.ts + import { Auth0Server, registerAuth0Instance } from '@auth0/auth0-react-router/server'; + + export const auth0 = new Auth0Server(); + registerAuth0Instance(auth0); + ``` + + + + Create a splat route that handles all `/auth/*` paths. `handleAuth` dispatches internally to `handleLogin`, `handleCallback`, `handleLogout`, and `handleBackchannelLogout` based on the URL path and HTTP method. + + ```tsx app/routes/auth.$.tsx + import { handleAuth } from '@auth0/auth0-react-router/server'; + import { auth0 } from '../auth0.server'; + + export const loader = ({ request }: { request: Request }) => + handleAuth(auth0, request); + + export const action = ({ request }: { request: Request }) => + handleAuth(auth0, request); + ``` + + Register the route in your route config: + + ```ts app/routes.ts + import { type RouteConfig, route } from '@react-router/dev/routes'; + + export default [ + route('auth/*', 'routes/auth.$.tsx'), + // ... your other routes + ] satisfies RouteConfig; + ``` + + + + Add `Auth0Provider` and `rootAuthLoader` to `app/root.tsx`. `rootAuthLoader` decrypts the session cookie and passes the auth state to the provider — no tokens are sent to the browser. + + ```tsx app/root.tsx expandable + import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router'; + import { Auth0Provider } from '@auth0/auth0-react-router'; + import { rootAuthLoader } from '@auth0/auth0-react-router/server'; + import type { Route } from './+types/root'; + + export const loader = ({ request }: Route.LoaderArgs) => + rootAuthLoader(request); + + export default function Root() { + return ( + + + + + + + + + + + + + + + + ); + } + ``` + + + `Auth0Provider` reads session data from `useRouteLoaderData('root')`, so the root route must have the id `root`. With file-based routing React Router sets this from the filename automatically. With a custom route config, pass `{ id: 'root' }` to the `layout()` call. + + + + + Use the built-in components to show login and logout controls. `LoginButton` redirects to `/auth/login` and `LogoutButton` redirects to `/auth/logout`. Auth0 handles the OIDC flow and redirects the user back to your app after sign-in. + + ```tsx app/routes/_index.tsx + import { + AuthLoading, + LoginButton, + LogoutButton, + SignedIn, + SignedOut, + } from '@auth0/auth0-react-router'; + + export default function Home() { + return ( +
+

Welcome

+ +

Loading…

+
+ + Log in + + + Log out + +
+ ); + } + ``` +
+ + + Use the `useUser` hook to access the authenticated user's profile in any client component. Pair it with `requireSession` in the loader to block unauthenticated requests at the server before the page renders. + + ```tsx app/routes/profile.tsx + import { useUser } from '@auth0/auth0-react-router'; + import { requireSession } from '@auth0/auth0-react-router/server'; + import type { Route } from './+types/profile'; + + export const loader = async ({ request }: Route.LoaderArgs) => { + await requireSession(request); + return null; + }; + + export default function Profile() { + const user = useUser(); + + return ( +
+

Profile

+ {user && ( +
+ {user.name +

{user.name}

+

{user.email}

+
+ )} +
+ ); + } + ``` +
-```shell -npm run dev -``` + + ```shellscript + npm run dev + ``` -Open `http://localhost:5173` in your browser and click **Log in**. You will be redirected to the Auth0 Universal Login page. After signing in you will be redirected back to your app. + Open `http://localhost:5173` in your browser and click **Log in**. You will be redirected to the Auth0 Universal Login page. After signing in you will be redirected back to your app. + +
-Your app now has working login and logout. The session is stored in a JWE-encrypted cookie — access tokens stay on the server and are never sent to the browser. + Your app now has working login and logout. The session is stored in a JWE-encrypted cookie — access tokens stay on the server and are never sent to the browser. - - ## Troubleshooting @@ -404,7 +413,7 @@ Requests without the required role receive a `403`. The SDK can run in a purely client-side mode backed by `@auth0/auth0-spa-js`. Add `VITE_AUTH0_DOMAIN` and `VITE_AUTH0_CLIENT_ID` to your `.env` — `Auth0Provider` detects these automatically and switches to the PKCE flow. No other code changes are required. -```shell +```shellscript # .env additions for SPA mode VITE_AUTH0_DOMAIN={yourDomain} VITE_AUTH0_CLIENT_ID={yourClientId}