> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Router アプリケーションにログインを追加する

> このガイドでは、Auth0 React Router SDK を使用して、React Router アプリケーション（フレームワークモード、v7 以降）に Auth0 を統合する方法を説明します。

> [!WARNING]
>
> `@auth0/auth0-react-router` は現在 **Beta** 版 (`1.0.0-beta.2`) です。安定版 1.0 のリリースまでに API が変更される可能性があります。

> [accordion] AI を使って Auth0 を統合する
>
> Claude Code、Cursor、GitHub Copilot などの AI コーディングアシスタントをお使いの場合は、[エージェントスキル](https://agentskills.io/home)を使えば、数分で Auth0 認証を自動的に追加できます。
>
> **インストール：**
>
> ```bash theme={null}
> npx skills add auth0/agent-skills --skill auth0
> ```
>
> **次に、AI アシスタントに次のように依頼します：**
>
> ```text theme={null}
> Add Auth0 authentication to my React Router app
> ```
>
> AI アシスタントが、Auth0 アプリケーションの作成、資格情報の取得、`@auth0/auth0-react-router` のインストール、プロバイダーの構成、ルートのセットアップまでを自動で行います。[エージェントスキルの詳細なドキュメント →](https://auth0.com/docs/ja-jp/quickstart/agent-skills.md)

**前提条件：** 始める前に、以下がインストールされていることを確認してください。

* **[Node.js](https://nodejs.org/en/download)** 18 以降 (20 LTS 推奨)
* **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 9 以降、**[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22 以降、または **[pnpm](https://pnpm.io/installation)** 8 以降
* **[jq](https://jqlang.org/)** - Auth0 CLI でのセットアップに必要
* React Router のフレームワークモード (v7 以降、`react-router.config.ts` があること)

## はじめに

このクイックスタートでは、React RouterアプリケーションにAuth0の認証を追加する方法を説明します。Auth0 React Router SDKを使用して、ログイン、ログアウト、ユーザープロファイルの機能を備えたセキュアなアプリを構築します。SDKはOIDCフローをサーバー側で処理し、セッションをJWEで暗号化されたクッキーに保存するため、トークンがブラウザーに渡ることは一切ありません。

**1. 新しい React Router プロジェクトを作成する**

このクイックスタート用に、新しい React Router プロジェクトを作成します。

```shellscript theme={null}
npx create-react-router@latest my-app
```

プロジェクトを開きます。

```shellscript theme={null}
cd my-app && npm install
```

> [!NOTE]
>
> 既存のReact RouterアプリにAuth0を追加する場合は、この手順を省略してください。

**2. Auth0 React Router SDKをインストールする**

```shellscript theme={null}
npm install @auth0/auth0-react-router
```

**3. Auth0を設定する**

Auth0アプリケーションを作成し、コールバックURLとログアウトURLを設定します。

> [tab] クイックセットアップ

> [tab] CLI
>
> プロジェクトのルートディレクトリで次のコマンドを実行し、Auth0アプリの作成と`.env`ファイルの生成を行います。
>
> ```shellscript Mac theme={null}
> # Auth0 CLIをインストールする（未インストールの場合）
> brew tap auth0/auth0-cli && brew install auth0
>
> # Auth0アプリをセットアップし、.envファイルを生成する
> auth0 qs setup --app --type regular --framework react-router --port 5173 --name "My React Router App"
> ```
>
> ```powershell Windows theme={null}
> # Auth0 CLIをインストールする（未インストールの場合）
> scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
> scoop install auth0
>
> # Auth0アプリをセットアップし、.envファイルを生成する
> auth0 qs setup --app --type regular --framework react-router --port 5173 --name "My React Router App"
> ```
>
> > [!NOTE]
> >
> > このコマンドを実行すると、`http://localhost:5173`向けに構成されたAuth0のRegular Web Applicationが作成され、必要な資格情報をすべて含む`.env`ファイルが生成されます。この方法を使用する場合、手順4は不要です。

> [tab] Dashboard
>
> 1. [Auth0 Dashboard](https://manage.auth0.com/)で **\[Applications] > \[Applications]** に移動します
> 2. **\[Create Application]** をクリックし、名前を入力して **\[Regular Web Application]** を選択します
> 3. **\[Create]** をクリックします
> 4. **\[Settings]** タブ (アプリケーション設定) を開きます
> 5. 次のフィールドを設定します。
>
> | フィールド | 値 |
> | - | - |
> | Allowed Callback URLs | `http://localhost:5173/auth/callback` |
> | Allowed Logout URLs | `http://localhost:5173` |
>
> 6. **\[Save Changes]** をクリックします
> 7. アプリケーション設定の **\[Domain]** と **\[Client ID]** をコピーします。これらは次の手順で使用します

**4. 環境変数を設定する**

プロジェクトのルートに `.env` ファイルを作成します。

| 変数 | 確認場所 |
| - | - |
| `AUTH0_DOMAIN` | アプリケーションの設定 → ドメイン |
| `AUTH0_CLIENT_ID` | アプリケーションの設定 → クライアント ID |
| `AUTH0_CLIENT_SECRET` | アプリケーションの設定 → クライアントシークレット |
| `AUTH0_SESSION_SECRET` | 32 文字以上のランダムな文字列 (上記のスニペットで自動生成されます) |
| `AUTH0_APP_BASE_URL` | アプリのベース URL (ローカル開発では `http://localhost:5173`) |

> [!WARNING]
>
> `.env` は決してバージョン管理にコミットしないでください。最初のコミットを行う前に、必ず `.gitignore` に追加しておきましょう。

**5. Auth0のサーバーインスタンスを作成する**

`app/auth0.server.ts` を作成します。`.server.ts` という接尾辞が付いたファイルは React Router のバンドラーによってクライアントバンドルから除外されるため、シークレットをサーバー側だけに留めておけます。

```ts app/auth0.server.ts theme={null}
import { Auth0Server, registerAuth0Instance } from '@auth0/auth0-react-router/server';

export const auth0 = new Auth0Server();
registerAuth0Instance(auth0);
```

**6. 認証ルートを追加する**

`/auth/*` 配下のすべてのパスを処理するスプラットルートを作成します。`handleAuth` は、URL のパスと HTTP メソッドに応じて、内部で `handleLogin`、`handleCallback`、`handleLogout`、`handleBackchannelLogout` に処理を振り分けます。

```tsx app/routes/auth.$.tsx theme={null}
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);
```

ルート設定にルートを登録します。

```ts app/routes.ts theme={null}
import { type RouteConfig, route } from '@react-router/dev/routes';

export default [
  route('auth/*', 'routes/auth.$.tsx'),
  // ... その他のルート
] satisfies RouteConfig;
```

**7. ルートレイアウトを設定する**

`app/root.tsx` に `Auth0Provider` と `rootAuthLoader` を追加します。`rootAuthLoader` はセッションクッキーを復号し、認証状態をプロバイダーに渡します。トークンがブラウザーに送信されることはありません。

```tsx app/root.tsx expandable theme={null}
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 (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        <Auth0Provider>
          <Outlet />
        </Auth0Provider>
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}
```

> [!NOTE]
>
> `Auth0Provider` は `useRouteLoaderData('root')` からセッションデータを読み取るため、ルートのルート (root route) の id を `root` にする必要があります。ファイルベースのルーティングでは、React Router がファイル名をもとにこの id を自動で設定します。カスタムのルート設定を使用する場合は、`layout()` の呼び出しに `{ id: 'root' }` を渡してください。

**8. ログインとログアウトを追加**

組み込みのコンポーネントを使用して、ログインボタンとログアウトボタンを表示します。`LoginButton` は `/auth/login` に、`LogoutButton` は `/auth/logout` にリダイレクトします。OIDC フローは Auth0 が処理し、サインイン後にユーザーをアプリへリダイレクトして戻します。

```tsx app/routes/_index.tsx theme={null}
import {
  AuthLoading,
  LoginButton,
  LogoutButton,
  SignedIn,
  SignedOut,
} from '@auth0/auth0-react-router';

export default function Home() {
  return (
    <main>
      <h1>Welcome</h1>
      <AuthLoading>
        <p>Loading…</p>
      </AuthLoading>
      <SignedOut>
        <LoginButton>Log in</LoginButton>
      </SignedOut>
      <SignedIn>
        <LogoutButton>Log out</LogoutButton>
      </SignedIn>
    </main>
  );
}
```

**9. ユーザープロファイルを表示**

`useUser` Hooksを使うと、任意のクライアントコンポーネントから認証済みユーザーのプロフィールにアクセスできます。さらにローダーで `requireSession` と組み合わせれば、ページのレンダリング前に未認証のリクエストをサーバー側でブロックできます。

```tsx app/routes/profile.tsx theme={null}
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 (
    <main>
      <h1>Profile</h1>
      {user && (
        <div>
          <img src={user.picture} alt={user.name ?? ''} width={80} height={80} />
          <p><strong>{user.name}</strong></p>
          <p>{user.email}</p>
        </div>
      )}
    </main>
  );
}
```

**10. アプリケーションを実行する**

```shellscript theme={null}
npm run dev
```

ブラウザーで `http://localhost:5173` を開き、**Log in** をクリックします。Auth0のユニバーサルログインページにリダイレクトされます。サインインすると、アプリにリダイレクトされて戻ってきます。

> [!TIP]
>
> これで、アプリのログインとログアウトが機能するようになりました。セッションはJWEで暗号化されたクッキーに保存され、アクセストークンはサーバー上に保持されるため、ブラウザーに送信されることはありません。

## トラブルシューティング

> [accordion] JWEDecryptionFailed — セッションクッキーを復号できない
>
> \*\*原因：\*\*セッションクッキーの発行後に`AUTH0_SESSION_SECRET`が変更されたか、値が32文字未満です。
>
> **解決方法：**`localhost`のブラウザークッキーを削除し、`AUTH0_SESSION_SECRET`が32文字以上であることを確認してから、開発サーバーを再起動してください。新しいシークレットは`openssl rand -hex 32`で生成できます。

> [accordion] Callback URLの不一致 — ログイン後にAuth0がエラーを返す
>
> \*\*原因：\*\*Auth0が受け取ったリダイレクトURLが、Allowed Callback URLsに登録されたどの値とも一致していません。
>
> **解決方法：**[Auth0 Dashboard](https://manage.auth0.com/)で **\[Applications] > \[Applications]** に移動してアプリを選択し、**\[Application Settings]** で **\[Allowed Callback URLs]** が`http://localhost:5173/auth/callback`に設定されていることを確認します。末尾のスラッシュや余分な空白があれば削除し、**\[Save Changes]** をクリックしてください。

> [accordion] /auth/loginで404 — ルートが見つからない
>
> **原因：**`auth.$.tsx`スプラットルートが存在しないか、`routes.ts`に登録されていません。
>
> **解決方法：**`app/routes/auth.$.tsx`が存在し、`app/routes.ts`に`route('auth/*', 'routes/auth.$.tsx')`が含まれていることを確認してください。`routes.ts`を編集した後は、開発サーバーを再起動してください。

> [accordion] ログイン後にuseUserがnullを返す
>
> **原因：**`rootAuthLoader`が`app/root.tsx`からエクスポートされていないか、ルートルートのidが`root`になっていません。
>
> **解決方法：**`app/root.tsx`で`export const loader = ({ request }) => rootAuthLoader(request)`がエクスポートされていることを確認してください。カスタムのルート構成を使用している場合は、ルートレイアウトを`layout('root.tsx', { id: 'root' }, [...routes])`として登録してください。

> [accordion] context.getでTypeError — ミドルウェアが動作しない
>
> **原因：**`defineRouteAuth`と`auth0Middleware`を使用するには、ミドルウェアAPIが導入されたReact Router 7.9.0以降が必要です。
>
> **解決方法：**`react-router`を`>=7.9.0`にアップグレードしてください。または、各ローダーで`requireSession` / `requireUser`を使用して、ルートを個別に保護することもできます。

## 高度な使い方

> [accordion] アクセストークンでバックエンドAPIを呼び出す
>
> `.env`に`AUTH0_AUDIENCE`を追加し、APIの識別子を設定します (識別子は[Auth0 Dashboard](https://manage.auth0.com/) → **Applications > APIs** → **API Settings → Identifier**で確認できます) 。次に、ローダー内で`getAccessToken`を使用します。この方法なら、トークンがブラウザーに渡ることはありません。
>
> ```ts app/routes/data.tsx theme={null}
> 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 };
> };
> ```

> [accordion] ロールベースのルート保護
>
> `defineRouteAuth`ミドルウェア (React Router 7.9.0以降) を使用すると、ルート単位でロールによるアクセス制御を適用できます。ロールはデフォルトで`https://auth0.com/claims/roles`クレームから読み取られます。
>
> ```ts app/routes/admin.tsx theme={null}
> 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 };
> };
> ```
>
> 必要なロールを持たないリクエストには`403`が返されます。

> [accordion] SPAモード（クライアント側PKCE）
>
> SDKは、`@auth0/auth0-spa-js`をベースにした完全なクライアント側モードでも動作します。`.env`に`VITE_AUTH0_DOMAIN`と`VITE_AUTH0_CLIENT_ID`を追加すると、`Auth0Provider`がこれらを自動的に検出してPKCEフローに切り替えます。ほかにコードを変更する必要はありません。
>
> ```shellscript theme={null}
> # SPAモード用に.envへ追加する項目
> VITE_AUTH0_DOMAIN={yourDomain}
> VITE_AUTH0_CLIENT_ID={yourClientId}
> ```
>
> > [!WARNING]
> >
> > `AUTH0_*`変数と`VITE_AUTH0_*`変数を同時に設定しないでください。ハイブリッドモードはサポートされていないため、両方が設定されていると、SPAでログアウトしてもサーバー側のセッションクッキーが削除されません。
