> ## 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 アプリケーションに Login を追加する

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

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 />;
};

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

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

<HowToSchema />

export const envSnippet = `AUTH0_DOMAIN={yourDomain}
AUTH0_CLIENT_ID={yourClientId}
AUTH0_CLIENT_SECRET={yourClientSecret}
APP_BASE_URL=http://localhost:3000
AUTH0_SESSION_SECRET=use-a-long-random-string-at-least-32-characters`;

export const envSnippetDashboard = `AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID
AUTH0_CLIENT_SECRET=YOUR_AUTH0_CLIENT_SECRET
APP_BASE_URL=http://localhost:3000
AUTH0_SESSION_SECRET=use-a-long-random-string-at-least-32-characters`;

<Warning>
  このQuickstartは現在**Beta**版です。ぜひフィードバックをお寄せください！
</Warning>

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  **前提条件:** 始める前に、以下がインストールされていることを確認してください。

  * [Node.js](https://nodejs.org/) 22 LTS以降
  * [npm](https://www.npmjs.com/) 10以降、または[yarn](https://yarnpkg.com/) 1.22以降
</Callout>

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

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

<Steps>
  <Step title="新しいプロジェクトを作成する" stepNumber={1}>
    Express アプリケーション用の新しいディレクトリを作成し、Node.js プロジェクトを初期化します。

    <AuthCodeGroup>
      ```shellscript Mac theme={null}
      mkdir auth0-express-app && cd auth0-express-app
      npm init -y
      touch server.js .env
      ```

      ```shellscript Windows theme={null}
      mkdir auth0-express-app; cd auth0-express-app
      npm init -y
      New-Item server.js, .env
      ```
    </AuthCodeGroup>

    `package.json` を更新して ES モジュールを使用し、起動スクリプトを追加します。

    ```json theme={null}
    {
      "name": "auth0-express-app",
      "version": "1.0.0",
      "type": "module",
      "main": "server.js",
      "scripts": {
        "start": "node server.js",
        "dev": "node --watch server.js"
      }
    }
    ```
  </Step>

  <Step title="SDK をインストールする" stepNumber={2}>
    `@auth0/auth0-express`、`express`、`dotenv` をインストールします。

    ```shell theme={null}
    npm install @auth0/auth0-express@beta express dotenv
    ```
  </Step>

  <Step title="Auth0 を設定する" stepNumber={3}>
    Auth0 テナントに新しいアプリケーションを作成し、環境変数を設定します。

    <Tabs>
      <Tab title="クイックセットアップ">
        <CreateInteractiveApp placeholderText="Express" appType="regular_web" allowedCallbackUrls={["http://localhost:3000/auth/callback"]} allowedLogoutUrls={["http://localhost:3000"]} />

        アプリケーションを作成したら、以下の値を `.env` ファイルに追加します。

        <AuthCodeBlock children={envSnippet} language="shellscript" filename=".env" />

        安全なセッションシークレットを生成します。

        ```shell theme={null}
        node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
        ```

        出力をコピーして、`AUTH0_SESSION_SECRET` の値として使用します。

        <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
          macOS または Linux では、`openssl rand -hex 32` も実行できます。Node はすでに前提条件となっているため、この Node コマンドはすべてのプラットフォームで使用できます。
        </Callout>
      </Tab>

      <Tab title="CLI">
        プロジェクトのルートディレクトリで以下のコマンドを実行し、Auth0 アプリケーションを作成します。

        <AuthCodeGroup>
          ```shellscript Mac theme={null}
          AUTH0_APP_NAME="My Express App" && \
          auth0 apps create \
            -n "${AUTH0_APP_NAME}" \
            -t regular \
            --callbacks http://localhost:3000/auth/callback \
            --logout-urls http://localhost:3000 \
            --json | jq -r '"AUTH0_DOMAIN=\(.domain)\nAUTH0_CLIENT_ID=\(.client_id)\nAUTH0_CLIENT_SECRET=\(.client_secret)\nAPP_BASE_URL=http://localhost:3000\nAUTH0_SESSION_SECRET='$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")'"' > .env
          ```

          ```powershell Windows theme={null}
          $appName = "My Express App"
          $secret = [System.Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
          auth0 apps create -n $appName -t regular `
            --callbacks http://localhost:3000/auth/callback `
            --logout-urls http://localhost:3000 `
            --json | ConvertFrom-Json | ForEach-Object {
              "AUTH0_DOMAIN=$($_.domain)`nAUTH0_CLIENT_ID=$($_.client_id)`nAUTH0_CLIENT_SECRET=$($_.client_secret)`nAPP_BASE_URL=http://localhost:3000`nAUTH0_SESSION_SECRET=$secret"
            } | Out-File .env -Encoding utf8
          ```
        </AuthCodeGroup>

        <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
          Auth0 CLI をまだインストールしていない場合は、次のコマンドを実行します。

          ```shell theme={null}
          brew tap auth0/auth0-cli && brew install auth0
          ```

          次に、`auth0 login` で認証します。
        </Callout>
      </Tab>

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

        | フィールド                 | 値                                     |
        | --------------------- | ------------------------------------- |
        | Allowed Callback URLs | `http://localhost:3000/auth/callback` |
        | Allowed Logout URLs   | `http://localhost:3000`               |

        6. **変更を保存** をクリックします
        7. **Basic Information** から **Domain**、**Client ID**、**Client Secret** をコピーします

        `.env` ファイルを作成します。

        <AuthCodeBlock children={envSnippetDashboard} language="shellscript" filename=".env" />

        <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
          `YOUR_AUTH0_DOMAIN`、`YOUR_AUTH0_CLIENT_ID`、`YOUR_AUTH0_CLIENT_SECRET` を、Auth0 アプリケーションの設定値に置き換えます。
        </Callout>

        安全なセッションシークレットを生成し、プレースホルダー値を置き換えます。

        ```shell theme={null}
        node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
        ```

        <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
          macOS または Linux では、`openssl rand -hex 32` も実行できます。Node はすでに前提条件となっているため、この Node コマンドはすべてのプラットフォームで使用できます。
        </Callout>
      </Tab>
    </Tabs>
  </Step>

  <Step title="middleware を設定する" stepNumber={4}>
    Expressアプリケーションに`createAuth0()`ミドルウェアを追加します。SDKによって、`/auth/login`、`/auth/logout`、`/auth/callback`、`/auth/backchannel-logout`の各ルートが自動的に設定されます。

    ```javascript server.js theme={null}
    import 'dotenv/config';
    import express from 'express';
    import { createAuth0 } from '@auth0/auth0-express';

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

    app.use(createAuth0());

    app.get('/', async (req, res) => {
      const session = await req.auth0.client.getSession();
      res.send(session ? 'Logged in' : 'Logged out');
    });

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

    **この処理で行われること:**

    * `createAuth0()` は、環境変数 (`AUTH0_DOMAIN`、`AUTH0_CLIENT_ID` など) から資格情報を自動的に読み取ります
    * `/auth/` 配下に4つの認証ルートをマウントします
    * セッションとトークンにアクセスできるよう、すべてのリクエストに `req.auth0.client` を追加します
  </Step>

  <Step title="ログイン、ログアウト、保護されたプロファイルルートを追加" stepNumber={5}>
    SDK の `requiresAuth` ミドルウェアでルートを保護し、`getUser()` を使用してユーザープロファイルデータを表示します。

    ```javascript server.js theme={null}
    import 'dotenv/config';
    import express from 'express';
    import { createAuth0, requiresAuth } from '@auth0/auth0-express';

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

    app.use(createAuth0());

    // 公開のホームルート
    app.get('/', async (req, res) => {
      const session = await req.auth0.client.getSession();
      const isAuthenticated = !!session;

      res.send(`
        <html>
          <head>
            <title>Auth0 Express (Beta) 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; }
              .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 (Beta) 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="/auth/logout">Logout</a>'
                : '<a href="/auth/login">Login</a>'}
            </nav>
          </body>
        </html>
      `);
    });

    // 保護されたプロファイルのルート — requiresAuth は未認証のユーザーを /auth/login にリダイレクトします
    app.get('/profile', requiresAuth(), async (req, res) => {
      const user = await req.auth0.client.getUser();

      res.send(`
        <html>
          <head>
            <title>Profile</title>
            <style>
              body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 2rem; max-width: 600px; margin: 0 auto; }
              pre { background: #f4f4f4; padding: 1rem; border-radius: 4px; overflow-x: auto; }
              img { border-radius: 50%; }
            </style>
          </head>
          <body>
            <h1>User Profile</h1>
            ${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>
            <h3>Full Profile</h3>
            <pre>${JSON.stringify(user, null, 2)}</pre>
            <a href="/">← Back</a> | <a href="/auth/logout">Logout</a>
          </body>
        </html>
      `);
    });

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

    **要点:**

    * `@auth0/auth0-express` の `requiresAuth()` はルートを保護し、未認証のユーザーを `/auth/login` にリダイレクトします
    * `req.auth0.client.getUser()` は認証済みユーザーのプロファイルを返します
    * ログインリンクは `/auth/login`、ログアウトは `/auth/logout` を指し、どちらも自動的にマウントされます
  </Step>

  <Step title="アプリケーションを実行する" stepNumber={6}>
    開発サーバーを起動します：

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

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

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

      これで、完全に機能する Auth0 のログインフローが完成しました。以下を行うと:

      1. **Login** をクリック — Auth0 の Universal Login ページにリダイレクトされます
      2. 認証を完了 — `/auth/callback` にあるアプリにリダイレクトされます
      3. `/profile` にアクセス — ユーザー情報が表示されます
      4. **Logout** をクリック — セッションがクリアされ、Auth0 からログアウトします
    </Check>
  </Step>
</Steps>

***

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

<AccordionGroup>
  <Accordion title="アクセストークン を使用して保護された API を呼び出す">
    SDK を `audience` で設定して API 用の アクセストークン をリクエストし、`getAccessToken()` で取得します。

    API の audience を `.env` に追加します。

    ```shell .env theme={null}
    AUTH0_AUDIENCE=https://your-api.example.com
    ```

    保護された ルート 内で token を取得します。

    ```javascript server.js theme={null}
    app.get('/api-data', requiresAuth(), async (req, res) => {
      const { accessToken } = await req.auth0.client.getAccessToken();

      const response = await fetch('https://your-api.example.com/data', {
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      res.json(await response.json());
    });
    ```

    SDK は アクセストークン の有効期限が切れると、自動的に token を refresh します。
  </Accordion>

  <Accordion title="returnTo を使用したカスタム login">
    `returnTo` パラメータを使用して、login 後にユーザーを指定したページへリダイレクトします。

    ```javascript server.js theme={null}
    app.get('/dashboard', async (req, res) => {
      const session = await req.auth0.client.getSession();
      if (!session) {
        return res.redirect('/auth/login?returnTo=/dashboard');
      }
      res.send('Welcome to your dashboard!');
    });
    ```
  </Accordion>

  <Accordion title="カスタム authorization middleware">
    セッション を基盤に、独自の authorization ロジックを構築します。

    ```javascript server.js theme={null}
    async function requireAdmin(req, res, next) {
      const user = await req.auth0.client.getUser();
      if (!user) return res.redirect('/auth/login');
      if (!user['https://myapp.com/roles']?.includes('admin')) {
        return res.status(403).send('Forbidden');
      }
      next();
    }

    app.get('/admin', requireAdmin, (req, res) => {
      res.send('Admin panel');
    });
    ```

    `https://myapp.com/roles` claim はデフォルトでは含まれていません。[Action](https://auth0.com/docs/customize/actions) を使用して ID トークンに追加し、namespaced claim 名を使用してください。
  </Accordion>
</AccordionGroup>

***

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

<AccordionGroup>
  <Accordion title="'req.auth0 is undefined'">
    **原因:** ルートハンドラーより前に `createAuth0()` ミドルウェアが登録されていません。

    **修正:** `req.auth0` にアクセスするルートより前に `app.use(createAuth0())` を記述してください。

    ```javascript theme={null}
    // ✅ Correct
    app.use(createAuth0());
    app.get('/profile', requiresAuth(), handler);

    // ❌ Wrong
    app.get('/profile', requiresAuth(), handler);
    app.use(createAuth0());
    ```
  </Accordion>

  <Accordion title="コールバック URL の不一致エラー">
    **原因:** Auth0 アプリケーションの設定で指定したコールバック URL が `http://localhost:3000/auth/callback` と一致していません。

    **修正:**

    1. [Auth0 Dashboard](https://manage.auth0.com/) → **アプリケーション > アプリケーション** → 対象のアプリ → **アプリケーション設定** に移動します
    2. **許可されるコールバック URL** に `http://localhost:3000/auth/callback` を追加します
    3. **許可されるログアウト URL** に `http://localhost:3000` を追加します
    4. **変更を保存** をクリックします

    注: `@auth0/auth0-express` SDK では `/auth/callback` を使用します (`express-openid-connect` で使用する `/callback` ではありません) 。
  </Accordion>

  <Accordion title="環境変数が読み込まれない">
    **原因:** `dotenv/config` がインポートされていないか、`.env` ファイルに必要な値が設定されていません。

    **修正:**

    1. エントリーファイルの先頭に `import 'dotenv/config'` (または `require('dotenv').config()`) を記述してください
    2. `.env` に必要な 5 つの変数 (`AUTH0_DOMAIN`、`AUTH0_CLIENT_ID`、`AUTH0_CLIENT_SECRET`、`APP_BASE_URL`、`AUTH0_SESSION_SECRET`) がすべて含まれていることを確認します
    3. 不足している値をデバッグします:

    ```javascript theme={null}
    console.log({
      domain: !!process.env.AUTH0_DOMAIN,
      clientId: !!process.env.AUTH0_CLIENT_ID,
      clientSecret: !!process.env.AUTH0_CLIENT_SECRET,
      appBaseUrl: !!process.env.APP_BASE_URL,
      sessionSecret: !!process.env.AUTH0_SESSION_SECRET,
    });
    ```
  </Accordion>

  <Accordion title="ログイン後の 'Invalid state' エラー">
    **原因:** セッション Cookie が正しく設定されていないか、コールバック URL に直接アクセスしています。

    **修正:**

    1. `APP_BASE_URL` がブラウザーでアクセスしている URL (例: `http://localhost:3000`) と一致していることを確認します
    2. ブラウザーの Cookie を削除して、再試行します
    3. 本番環境では HTTPS を使用していることを確認します
  </Accordion>
</AccordionGroup>

***

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

* **[Express API を保護する](/docs/ja-jp/quickstart/backend/express-api-beta)** — `@auth0/auth0-express-api` を使用して、API でアクセストークンを検証する
* **[Authorization を追加する](https://auth0.com/docs/manage-users/access-control/rbac)** — ロールベースのアクセス制御を実装する
* **[Universal Login をカスタマイズする](https://auth0.com/docs/customize/universal-login-pages)** — ログイン体験をブランドに合わせる
* **[Social Connections を追加する](https://auth0.com/docs/connections/social)** — Google、GitHub などのソーシャルログインを有効にする
* **[MFA を実装する](https://auth0.com/docs/secure/multi-factor-authentication)** — 多要素認証を追加する

***

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

* **[auth0/auth0-express GitHub](https://github.com/auth0/auth0-express/tree/main/packages/auth0-express)** — ソースコードとサンプル
* **[Auth0 Community](https://community.auth0.com/)** — コミュニティでサポートを受ける
