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

> このガイドでは、express-openid-connect SDK を使用して Auth0 を統合し、認証を追加して、Express.js Web アプリケーションにユーザープロファイル情報を表示する方法を説明します。

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

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

export const CreateInteractiveApp = ({placeholderText = "Auth0", appType = "regular_web", allowedCallbackUrls = ["localhost:3000"], allowedLogoutUrls = ["localhost:3000"], allowedOriginUrls = ["localhost:3000"]}) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [storeReady, setStoreReady] = useState(false);
  const [displayForm, setDisplayForm] = useState(true);
  useEffect(() => {
    const init = () => setStoreReady(true);
    if (window.rootStore) {
      window.rootStore.clientStore.setSelectedClient(null);
      window.rootStore.clientStore.setSelectedClientSecret(undefined);
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
    };
  }, []);
  useEffect(() => {
    if (!storeReady) return;
    const disposer = autorun(() => {
      const rootStore = window.rootStore;
      setIsAuthenticated(rootStore.sessionStore.isAuthenticated);
    });
    return () => {
      disposer();
    };
  }, [storeReady]);
  if (!storeReady || typeof window === "undefined" || !displayForm) {
    return <></>;
  }
  const login = () => {
    const baseUrl = window.rootStore.config.apiBaseUrl;
    const returnTo = encodeURIComponent(window.location.href);
    window.location.href = `${baseUrl}/auth/user/login?returnTo=${returnTo}`;
  };
  const Card = ({className = "", children}) => {
    return <div className={`
          flex border rounded-2xl
          border-gray-950/10 dark:border-white/10
          py-3.5 px-4 gap-2
          text-sm text-gray-900 dark:text-gray-200
          ${className}
        `}>
        {children}
      </div>;
  };
  const Button = ({children, ...props}) => {
    return <button className="bg-[--button-primary] text-[--foreground-inverse] px-[1.125rem] py-1.5 rounded-lg font-medium" {...props}>
        {children}
      </button>;
  };
  const CreateApplicationForm = () => {
    const [name, setName] = useState("");
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState("");
    const handleSubmit = async () => {
      if (!name.trim()) {
        setError("アプリケーション名は必須です");
        return;
      }
      setIsLoading(true);
      setError(null);
      try {
        await window.rootStore.clientStore.createClient({
          name: name.trim(),
          app_type: appType,
          callbacks: allowedCallbackUrls,
          allowed_logout_urls: allowedLogoutUrls,
          web_origins: allowedOriginUrls,
          client_metadata: {
            created_by: "quickstart-docs-app-creation-component"
          }
        });
        setDisplayForm(false);
      } catch (err) {
        console.error("Error creating client:", err);
        const errorMessage = err instanceof Error ? err.message : "アプリケーションの作成に失敗しました";
        setError(errorMessage);
      } finally {
        setIsLoading(false);
      }
    };
    return <Card className="flex-col items-start p-4 gap-3.75">
        <span className="font-medium text-gray-900 dark:text-gray-200">Auth0 アプリを作成</span>
        <div className="w-full flex gap-2">
          <input id="app-name" name={name} className="
              w-full max-w-[448px] h-11 py-2 px-4 
              border rounded-lg border-gray-950/10 dark:border-white/10 
              text-gray-900 dark:text-gray-200
              focus:outline-none dark:focus:outline-none
            " placeholder={`マイ ${placeholderText} アプリ`} value={name} onChange={e => setName(e.target.value)} />
          <Button onClick={handleSubmit}>{isLoading ? "作成中…" : "作成"}</Button>
        </div>
        {error && <p className="text-red-500">{error}</p>}
      </Card>;
  };
  const SignInForm = () => {
    return <Card className="items-center">
        <Button onClick={login}>ログイン</Button> <span>アプリを作成するには</span>
      </Card>;
  };
  return isAuthenticated ? <CreateApplicationForm /> : <SignInForm />;
};

<HowToSchema />

<Callout icon="pencil" color="#FFC107" iconType="solid">
  `@auth0/auth0-express` SDK を使用するこの Quickstart の新しい **Beta** バージョンが利用可能です。まもなくこのガイドに代わる予定です。[Beta Quickstart を試す →](/docs/ja-jp/quickstart/webapp/express-beta)
</Callout>

<Accordion title="AI を使って Auth0 を統合する" icon="microchip-ai" iconType="solid" defaultOpen>
  Claude Code、Cursor、GitHub Copilot などの AI コーディングアシスタントを使用している場合は、[agent skills](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 Express app
  ```

  AI アシスタントが自動的に Auth0 アプリケーションを作成し、資格情報を取得して、`express-openid-connect` をインストールし、ミドルウェアを設定し、ルートをセットアップします。[agent skills の完全なドキュメント →](/docs/ja-jp/quickstart/agent-skills)
</Accordion>

<Note>
  **前提条件:** 開始する前に、以下がインストールされていることを確認してください。

  * [Node.js](https://nodejs.org/) 18 LTS 以降
  * [npm](https://www.npmjs.com/) 10+ または [yarn](https://yarnpkg.com/) 1.22+
  * [jq](https://jqlang.github.io/jq/) - Auth0 CLI の設定に必要 (任意)

  **Express のバージョン互換性:** この Quickstart は Express 4.17.0 以降で動作します。
</Note>

<div id="get-started">
  ## はじめに
</div>

このガイドでは、`express-openid-connect` SDK を使用して Express.js の Web アプリケーションに Auth0 を統合し、認証を追加して、ユーザープロファイル情報を表示する方法を紹介します。

***

<div id="1-create-a-new-project">
  ## 1. 新しいプロジェクトを作成する
</div>

Expressアプリケーション用の新しいディレクトリを作成し、Node.jsのプロジェクトを初期化します。

```bash theme={null}
mkdir auth0-express && cd auth0-express
```

```bash theme={null}
npm init -y
```

プロジェクトの構成を作成します:

```bash theme={null}
touch index.js .env
```

***

<div id="2-install-the-auth0-express-sdk">
  ## 2. Auth0 Express SDKをインストールする
</div>

環境変数を管理するため、Express と dotenv と一緒に `express-openid-connect` をインストールします。

```bash theme={null}
npm install express express-openid-connect dotenv
```

開発時には、ファイル変更時にサーバーを自動的に再起動できるよう、nodemon をインストールします：

```bash theme={null}
npm install --save-dev nodemon
```

`package.json` を更新して、start スクリプトを追加します。

📁 **package.json**

```json theme={null}
{
  "name": "auth0-express",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "dependencies": {
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "express-openid-connect": "^2.17.1"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  }
}
```

***

<div id="3-setup-your-auth0-app">
  ## 3. Auth0 App を設定する
</div>

次に、Auth0 テナントに新しいアプリケーションを作成し、環境変数をプロジェクトに追加します。

CLI コマンドを実行して Auth0 アプリを自動的に設定することも、Auth0 Dashboard から手動で設定することもできます。

<Tabs>
  <Tab title="CLI">
    次のシェルコマンドをプロジェクトのルートディレクトリで実行すると、Auth0 アプリケーションが作成され、`.env` ファイルが生成されます。

    <CodeGroup>
      ```shellscript Mac theme={null}
      # Auth0 CLI をインストールします（まだインストールしていない場合）
      brew tap auth0/auth0-cli && brew install auth0

      # Auth0 アプリを設定し、.env ファイルを生成します
      auth0 qs setup --app --type regular --framework express --port 3000 --name "My Express 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 express --port 3000 --name "My Express App"
      ```
    </CodeGroup>

    <Note>
      このコマンドは次の操作を行います。

      1. 認証済みかどうかを確認します (必要に応じてログインを求められます)
      2. `http://localhost:3000` 用に設定された Auth0 従来型Webアプリケーションを作成します
      3. `ISSUER_BASE_URL`、`CLIENT_ID`、`SECRET`、`BASE_URL` を含む `.env` ファイルを生成します
    </Note>
  </Tab>

  <Tab title="Dashboard">
    1. [Auth0 Dashboard](https://manage.auth0.com/dashboard/) に移動します
    2. **アプリケーション** → **Create Application** に移動します
    3. アプリケーション名を入力します (例: "My Express App")
    4. **従来型Webアプリケーション** を選択し、**Create** をクリックします
    5. **設定** タブで、次のように設定します

    | Setting               | Value                   |
    | --------------------- | ----------------------- |
    | Allowed Callback URLs | `http://localhost:3000` |
    | Allowed Logout URLs   | `http://localhost:3000` |

    6. 下にスクロールして **変更を保存** をクリックします
    7. **Basic Information** セクションから **Domain** と **Client ID** の値をコピーします

    以下の内容で `.env` ファイルを作成します。

    📁 **.env**

    ```bash theme={null}
    ISSUER_BASE_URL=https://YOUR_AUTH0_DOMAIN
    CLIENT_ID=YOUR_CLIENT_ID
    SECRET=use-a-long-random-string-at-least-32-characters
    BASE_URL=http://localhost:3000
    ```

    <Warning>
      `YOUR_AUTH0_DOMAIN` は Auth0 テナントのドメイン (例: `dev-abc123.us.auth0.com`) に、`YOUR_CLIENT_ID` は Auth0 Dashboard 上のアプリケーションの Client ID に置き換えてください。
    </Warning>

    セッション暗号化用の安全なシークレットを生成します。

    ```bash theme={null}
    openssl rand -hex 32
    ```

    出力をコピーし、`.env` ファイルの `SECRET` の値として使用します。
  </Tab>
</Tabs>

***

<div id="4-configure-the-middleware">
  ## 4. ミドルウェアを設定する
</div>

Auth0 のミドルウェアを Express アプリケーションに追加します。`auth()` ミドルウェアはセッション管理を行い、`/login`、`/logout`、`/callback` のルートを自動的に作成します。

📁 **index.js**

```javascript theme={null}
require('dotenv').config();
const express = require('express');
const { auth } = require('express-openid-connect');

const app = express();
const port = process.env.PORT || 3000;

// Auth0 の設定
const config = {
  authRequired: false,      // 公開ルートを許可する
  auth0Logout: true,        // Auth0 の logout エンドポイントを使用する
  secret: process.env.SECRET,
  baseURL: process.env.BASE_URL,
  clientID: process.env.CLIENT_ID,
  issuerBaseURL: process.env.ISSUER_BASE_URL,
};

// 認証ミドルウェアを適用する
app.use(auth(config));

// ホームルート - 公開
app.get('/', (req, res) => {
  res.send(req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out');
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
```

**この設定でできること:**

* `authRequired: false` により、認証済み・未認証を問わず、どちらのユーザーもデフォルトでルートにアクセスできます
* `auth0Logout: true` により、ユーザーはアプリだけでなく Auth0 からもログアウトされます
* ミドルウェアにより、`/login`、`/logout`、`/callback` のルートが自動的に提供されます
* ユーザーセッションは暗号化された Cookie に保存されます

***

<div id="5-create-login-logout-and-profile-routes">
  ## 5. ログイン、ログアウト、プロファイルのルートを作成する
</div>

次に、ログイン/ログアウト用のリンクと、認証が必要なプロファイルページを表示するルートを追加します。

📁 **index.js**

```javascript theme={null}
require('dotenv').config();
const express = require('express');
const { auth, requiresAuth } = require('express-openid-connect');

const app = express();
const port = process.env.PORT || 3000;

// Auth0の設定
const config = {
  authRequired: false,
  auth0Logout: true,
  secret: process.env.SECRET,
  baseURL: process.env.BASE_URL,
  clientID: process.env.CLIENT_ID,
  issuerBaseURL: process.env.ISSUER_BASE_URL,
};

// 認証ミドルウェアを適用する
app.use(auth(config));

// ホームルート - ログイン/ログアウトの状態を表示する
app.get('/', (req, res) => {
  const isAuthenticated = req.oidc.isAuthenticated();

  res.send(`
    <html>
      <head>
        <title>Auth0 Express Quickstart</title>
        <style>
          body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
          a { color: #0066cc; text-decoration: none; margin-right: 1rem; }
          a:hover { text-decoration: underline; }
          .status { padding: 1rem; border-radius: 4px; margin: 1rem 0; }
          .logged-in { background: #d4edda; color: #155724; }
          .logged-out { background: #f8d7da; color: #721c24; }
        </style>
      </head>
      <body>
        <h1>Auth0 Express Quickstart</h1>
        <div class="status ${isAuthenticated ? 'logged-in' : 'logged-out'}">
          ${isAuthenticated ? '✓ You are logged in' : '✗ You are logged out'}
        </div>
        <nav>
          ${isAuthenticated
            ? '<a href="/profile">Profile</a> | <a href="/logout">Logout</a>'
            : '<a href="/login">Login</a>'}
        </nav>
      </body>
    </html>
  `);
});

// 保護されたプロファイルルート - 認証が必要
app.get('/profile', requiresAuth(), (req, res) => {
  const user = req.oidc.user;

  res.send(`
    <html>
      <head>
        <title>Profile - Auth0 Express</title>
        <style>
          body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
          a { color: #0066cc; text-decoration: none; }
          img { border-radius: 50%; }
          pre { background: #f4f4f4; padding: 1rem; border-radius: 4px; overflow-x: auto; }
          .card { border: 1px solid #ddd; border-radius: 8px; padding: 1.5rem; margin: 1rem 0; }
        </style>
      </head>
      <body>
        <h1>User Profile</h1>
        <div class="card">
          ${user.picture ? `<img src="${user.picture}" alt="Profile" width="80" />` : ''}
          <h2>${user.name || user.nickname || 'User'}</h2>
          <p><strong>Email:</strong> ${user.email || 'N/A'}</p>
        </div>
        <h3>Full User Object</h3>
        <pre>${JSON.stringify(user, null, 2)}</pre>
        <nav>
          <a href="/">← Back to Home</a> | <a href="/logout">Logout</a>
        </nav>
      </body>
    </html>
  `);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
```

**要点:**

* `requiresAuth()` ミドルウェアは `/profile` ルートを保護し、未認証のユーザーはログイン画面にリダイレクトされます
* `req.oidc.user` には、認証済みユーザーのプロファイル情報が含まれます
* `req.oidc.isAuthenticated()` は、ログイン状態を示す真偽値を返します
* Login ルートと logout ルート (`/login`, `/logout`) は、`auth()` ミドルウェアによって自動的に作成されます

***

<div id="6-run-your-app">
  ## 6. アプリを実行する
</div>

開発サーバーを起動します：

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

ブラウザーで [http://localhost:3000](http://localhost:3000) を開きます。

<Check>
  **チェックポイント**

  これで、完全に機能する Auth0 のログインページが使えるようになっているはずです。次のように動作します。

  1. "Login" をクリックする - Auth0 の Universal Login ページにリダイレクトされます
  2. 認証を完了する - アプリにリダイレクトされます
  3. "/profile" にアクセスする - ユーザー情報が表示されます
  4. "Logout" をクリックする - アプリと Auth0 の両方からログアウトされます
</Check>

***

<div id="advanced-usage">
  ## 高度な使い方
</div>

<AccordionGroup>
  <Accordion title="requiresAuth() を使用して特定のルートを保護する">
    認証が必要な各ルートを保護するには、`requiresAuth()` ミドルウェアを使用します。

    ```javascript theme={null}
    const { auth, requiresAuth } = require('express-openid-connect');

    app.use(auth({ authRequired: false }));

    // 公開ルート
    app.get('/', (req, res) => {
      res.send('Welcome! This is public.');
    });

    // 保護されたルート
    app.get('/dashboard', requiresAuth(), (req, res) => {
      res.send(`Hello ${req.oidc.user.name}, welcome to your dashboard!`);
    });

    app.get('/settings', requiresAuth(), (req, res) => {
      res.send('Settings page - only for authenticated users');
    });
    ```

    Express Router を使って、特定のパス配下にあるすべてのルートを保護することもできます：

    ```javascript theme={null}
    const protectedRouter = express.Router();

    // このルーター内のすべてのルートで認証が必要
    protectedRouter.use(requiresAuth());

    protectedRouter.get('/dashboard', (req, res) => {
      res.send('Protected dashboard');
    });

    protectedRouter.get('/settings', (req, res) => {
      res.send('Protected settings');
    });

    app.use('/app', protectedRouter);
    // ルート: /app/dashboard、/app/settings はすべて保護済み
    ```
  </Accordion>

  <Accordion title="アクセストークンによる保護された API の呼び出し">
    外部APIの呼び出しにアクセストークンが必要な場合は、SDKを設定してアクセストークンを要求するようにします。

    📁 **index.js** (更新後の設定)

    ```javascript theme={null}
    const config = {
      authRequired: false,
      auth0Logout: true,
      secret: process.env.SECRET,
      baseURL: process.env.BASE_URL,
      clientID: process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
      clientSecret: process.env.CLIENT_SECRET,  // コードフローに必要
      authorizationParams: {
        response_type: 'code',
        audience: process.env.API_AUDIENCE,     // API 識別子
        scope: 'openid profile email read:data',
      },
    };
    ```

    以下を`.env`ファイルに追加してください:

    ```bash theme={null}
    CLIENT_SECRET=your_client_secret_from_dashboard
    API_AUDIENCE=https://your-api.example.com
    ```

    次に、アクセストークンを使って API を呼び出します：

    ```javascript theme={null}
    app.get('/api-data', requiresAuth(), async (req, res) => {
      try {
        let { token_type, access_token, isExpired, refresh } = req.oidc.accessToken;

        // トークンの有効期限が切れている場合は更新する
        if (isExpired()) {
          const refreshed = await refresh();
          access_token = refreshed.access_token;
        }

        // 保護されたAPIを呼び出す
        const response = await fetch('https://your-api.example.com/data', {
          headers: {
            Authorization: `${token_type} ${access_token}`,
          },
        });

        const data = await response.json();
        res.json(data);
      } catch (error) {
        console.error('API call failed:', error);
        res.status(500).json({ error: 'Failed to fetch data' });
      }
    });
    ```

    <Note>
      リフレッシュトークンを取得するには、スコープに `offline_access` を追加します。

      ```javascript theme={null}
      scope: 'openid profile email offline_access read:data',
      ```
    </Note>
  </Accordion>

  <Accordion title="クレームベース認可を使用する">
    ユーザーのクレーム (ロール、権限など) に基づいてルートを保護する：

    ```javascript theme={null}
    const { auth, requiresAuth, claimEquals, claimIncludes, claimCheck } = require('express-openid-connect');

    app.use(auth({ authRequired: false }));

    // role = 'admin' のユーザーのみ
    app.get('/admin', claimEquals('role', 'admin'), (req, res) => {
      res.send('Admin dashboard');
    });

    // roles 配列に 'editor' が含まれるユーザー
    app.get('/editor', claimIncludes('roles', 'editor'), (req, res) => {
      res.send('Editor dashboard');
    });

    // 条件付きカスタムクレームチェック
    app.get('/premium', claimCheck((req, claims) => {
      return claims.subscription === 'premium' || claims.role === 'admin';
    }), (req, res) => {
      res.send('Premium content');
    });
    ```

    <Note>
      `role` のようなクレームは、Auth0 ルールまたは Actions を使用してトークンに追加する必要があります。[カスタムクレームの追加方法について詳しくはこちら](https://auth0.com/docs/customize/actions/flows-and-triggers/login-flow/add-user-roles-to-id-and-access-tokens)。
    </Note>
  </Accordion>

  <Accordion title="カスタムセッションストア (Redis)">
    本番環境や複数のサーバーインスタンスで運用する場合は、独自のセッションストアを使用してください。

    ```bash theme={null}
    npm install redis connect-redis
    ```

    ```javascript theme={null}
    const { auth } = require('express-openid-connect');
    const { createClient } = require('redis');
    const RedisStore = require('connect-redis').default;

    // Redisクライアントを作成
    const redisClient = createClient({
      url: process.env.REDIS_URL || 'redis://localhost:6379',
    });
    redisClient.connect().catch(console.error);

    const config = {
      authRequired: false,
      auth0Logout: true,
      secret: process.env.SECRET,
      baseURL: process.env.BASE_URL,
      clientID: process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
      session: {
        store: new RedisStore({ client: redisClient }),
      },
    };

    app.use(auth(config));
    ```

    **カスタムセッションストアを使用するケース:**

    * 複数のサーバーインスタンスを運用している場合 (負荷分散)
    * セッションデータがCookieのサイズ制限 (約4KB) を超える場合
    * サーバーの再起動後もセッションを保持する必要がある場合
    * バックチャネルログアウトを使用する場合
  </Accordion>

  <Accordion title="エラー処理">
    認証エラーに対する適切なエラーハンドリングを追加します:

    ```javascript theme={null}
    const { auth } = require('express-openid-connect');

    app.use(auth({
      authRequired: false,
      auth0Logout: true,
      secret: process.env.SECRET,
      baseURL: process.env.BASE_URL,
      clientID: process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
      errorOnRequiredAuth: true,  // APIルートへのリダイレクトの代わりに401を返す
    }));

    // Custom error handler
    app.use((err, req, res, next) => {
      // Handle authentication errors
      if (err.statusCode === 401) {
        // For API requests, return JSON
        if (req.accepts('json')) {
          return res.status(401).json({
            error: 'Authentication required',
            login_url: '/login',
          });
        }
        // For browser requests, redirect to login
        return res.redirect('/login');
      }

      // Log the error (don't expose details to client)
      console.error('Application error:', err.message);

      res.status(err.statusCode || 500).json({
        error: 'An unexpected error occurred',
      });
    });
    ```
  </Accordion>
</AccordionGroup>

***

<div id="troubleshooting">
  ## トラブルシューティング
</div>

<AccordionGroup>
  <Accordion title="よくある問題と解決策">
    ### ログイン後に「Invalid state」エラーが発生する

    **問題:** 認証リクエストとコールバックの間で state が一致していません。

    **解決策:**

    1. 本番環境では HTTPS を使用していることを確認します
    2. Cookie が正しく設定されていることを確認します (ブラウザーでブロックされていないこと)
    3. Auth0 Dashboard でコールバック URL が完全に一致していることを確認します

    ### 「req.oidc is undefined」

    **問題:** `req.oidc` にアクセスする前に `auth()` ミドルウェアが適用されていません。

    **解決策:** `req.oidc` にアクセスするルートより前で `app.use(auth(config))` が呼び出されていることを確認します。

    ```javascript theme={null}
    // ✅ 正しい順序
    app.use(auth(config));
    app.get('/profile', requiresAuth(), (req, res) => { ... });

    // ❌ 間違った順序
    app.get('/profile', requiresAuth(), (req, res) => { ... });
    app.use(auth(config));
    ```

    ### セッションが大きすぎる / Cookie エラー

    **問題:** ユーザーのセッションデータが Cookie のサイズ制限を超えています。

    **解決策:** Redis のようなカスタムセッションストアを使用します。

    ```javascript theme={null}
    session: {
      store: new RedisStore({ client: redisClient }),
    }
    ```

    ### Callback URL の不一致

    **問題:** Auth0 から「Callback URL mismatch」エラーが返されます。

    **解決策:**

    1. Auth0 Dashboard → アプリケーション → あなたのアプリ → 設定 に移動します
    2. `http://localhost:3000` (または本番環境の URL) を **Allowed Callback URLs** に追加します
    3. URL は **完全に** 一致している必要があります (末尾のスラッシュを含む)

    ### 環境変数が読み込まれない

    **問題:** 設定値が `undefined` になっています。

    **解決策:**

    1. `require('dotenv').config()` がエントリーファイルの先頭にあることを確認します
    2. `.env` ファイルがルートディレクトリにあることを確認します
    3. 変数名にタイプミスがないか確認します

    ```javascript theme={null}
    // デバッグ: 設定値を出力します（本番環境では削除してください！）
    console.log('Config check:', {
      hasSecret: !!process.env.SECRET,
      hasClientID: !!process.env.CLIENT_ID,
      issuerBaseURL: process.env.ISSUER_BASE_URL,
    });
    ```
  </Accordion>
</AccordionGroup>

***

<div id="next-steps">
  ## 次のステップ
</div>

認証が機能するようになったので、次の内容もぜひご確認ください。

* **[認可を追加する](https://auth0.com/docs/manage-users/access-control/rbac)** - ロールベースのアクセス制御を実装する
* **[保護された API を呼び出す](https://auth0.com/docs/secure/tokens/access-tokens/get-access-tokens)** - アクセストークンを使用してバックエンド API を呼び出す
* **[Universal Login をカスタマイズする](https://auth0.com/docs/customize/universal-login-pages)** - ログイン画面をブランドに合わせる
* **[ソーシャル接続を追加する](https://auth0.com/docs/connections/social)** - Google、GitHub、その他のソーシャルログインを有効にする
* **[MFA を実装する](https://auth0.com/docs/secure/multi-factor-authentication)** - 多要素認証を追加する

***

<div id="resources">
  ## リソース
</div>

* **[express-openid-connect GitHub](https://github.com/auth0/express-openid-connect)** - ソースコードとサンプル
* **[API Documentation](https://auth0.github.io/express-openid-connect/)** - API の完全なリファレンス
* **[Auth0 Express Sample App](https://github.com/auth0-samples/auth0-express-webapp-sample)** - 完全なサンプルアプリケーション
* **[Auth0 Community](https://community.auth0.com/)** - Community からサポートを受ける
