> ## 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.js API を保護する

> このガイドでは、express-oauth2-jwt-bearer SDK を使用して、JWT アクセストークンで Express.js API エンドポイントを保護する方法を説明します。

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

<HowToSchema />

<Accordion title="AI を使用して Auth0 を統合する" icon="microchip-ai" iconType="solid" defaultOpen>
  Claude Code、Cursor、GitHub Copilot などの AI コーディングアシスタントを使用している場合は、[agent skills](https://agentskills.io/home) を使って、数分で Auth0 API の認証を自動的に追加できます。

  **インストール:**

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-express-api
  ```

  **次に、AI アシスタントに以下のように依頼します。**

  ```text theme={null}
  Add Auth0 JWT authentication to my Express API
  ```

  AI アシスタントは、Auth0 API を自動的に作成し、認証情報を取得して、`express-oauth2-jwt-bearer` をインストールし、JWT ミドルウェアを設定したうえで、トークン検証によって API エンドポイントを保護します。[agent skills の完全なドキュメント →](/ja/docs/quickstart/agent-skills)
</Accordion>

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

  * **[Node.js](https://nodejs.org/en/download)** 18 LTS 以降 (`^18.12.0 || ^20.2.0 || ^22.1.0 || ^24.0.0` をサポート)
  * **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 8 以降、**[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22 以降、または **[pnpm](https://pnpm.io/installation)** 8 以降

  インストールを確認するには、次を実行します: `node --version && npm --version`

  **Express のバージョン互換性:** このクイックスタートは **Express 4.x** と **Express 5.x** に対応しています。
</Note>

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

このクイックスタートでは、JWT アクセストークンを使用して Express.js API エンドポイントを保護する方法を説明します。Auth0 アクセストークンを検証し、ルートを保護して、スコープベースの認可を実装する安全な API を構築します。

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

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

    プロジェクトを初期化

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

    プロジェクト構成を作成する

    ```shellscript theme={null}
    touch server.js .env
    ```
  </Step>

  <Step title="express-oauth2-jwt-bearer SDK をインストールします" stepNumber={2}>
    必要な依存関係をインストールする

    ```shellscript theme={null}
    npm install express express-oauth2-jwt-bearer dotenv
    ```

    `package.json` に起動用スクリプトを追加します:

    ```json package.json theme={null}
    {
      "scripts": {
        "start": "node server.js",
        "dev": "node --watch server.js"
      }
    }
    ```
  </Step>

  <Step title="Auth0 API をセットアップする" stepNumber={3}>
    次に、Auth0 テナントに新しい API を作成し、環境変数をプロジェクトに追加します。

    Auth0 API の設定方法は 2 つあります。CLI コマンドを使う方法と、Dashboard から手動で設定する方法です。

    <Tabs>
      <Tab title="CLI">
        Auth0 API を作成するには、プロジェクトのルートディレクトリで次のコマンドを実行します。

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

          # Auth0 API を作成します
          auth0 apis create \
            --name "My Express API" \
            --identifier https://my-express-api.example.com
          ```

          ```powershell Windows theme={null}
          # Auth0 CLI をインストールします（まだインストールしていない場合）
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Auth0 API を作成します
          auth0 apis create `
            --name "My Express API" `
            --identifier https://my-express-api.example.com
          ```
        </CodeGroup>

        <Note>
          このコマンドで次の処理が実行されます。

          1. 認証済みかどうかを確認します (必要に応じてログインを求めます)
          2. 指定した識別子で Auth0 API を作成します
          3. ドメインや識別子を含む API の詳細を表示します
        </Note>

        作成後、**Identifier** と **Domain** の値をコピーし、`.env` ファイルを作成します。

        ```bash .env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
        ```

        <Note>
          `YOUR_AUTH0_DOMAIN` は Auth0 テナントのドメイン (例: `dev-abc123.us.auth0.com`) に、`YOUR_API_IDENTIFIER` は API 識別子 (例: `https://my-express-api.example.com`) に置き換えてください。
        </Note>
      </Tab>

      <Tab title="Dashboard">
        1. [Auth0 Dashboard](https://manage.auth0.com/dashboard/) を開きます
        2. **Applications** → **APIs** → **Create API** の順に進みます
        3. API の名前を入力します (例: "My Express API")
        4. **Identifier** を設定します (例: `https://my-express-api.example.com`)
           * これは API のオーディエンスであり、有効な URL 形式である必要があります
           * 実在する URL である必要はなく、単なる識別子です
        5. **Signing Algorithm** は **RS256** のままにします
        6. **Create** をクリックします
        7. **Settings** タブから **Identifier** の値をコピーします

        次の値を指定して `.env` ファイルを作成します。

        ```bash .env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
        ```

        <Note>
          `YOUR_AUTH0_DOMAIN` は Auth0 テナントのドメイン (例: `dev-abc123.us.auth0.com`) に、`YOUR_API_IDENTIFIER` は Dashboard の API 識別子 (例: `https://my-express-api.example.com`) に置き換えてください。
        </Note>
      </Tab>
    </Tabs>

    <Tip>
      `.env` ファイルが存在することを確認します: `cat .env` (Mac/Linux) または `type .env` (Windows)
    </Tip>
  </Step>

  <Step title="JWT ミドルウェアを設定する" stepNumber={4}>
    Express サーバーを作成し、JWT 検証を構成します。

    ```javascript server.js {1-3,6-7,10-13} lines theme={null}
    require('dotenv').config();
    const express = require('express');
    const { auth } = require('express-oauth2-jwt-bearer');

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

    // JWT検証ミドルウェアを設定する
    const checkJwt = auth({
      issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
      audience: process.env.AUTH0_AUDIENCE,
    });

    // サーバーを起動する
    app.listen(port, () => {
      console.log(`API server running at http://localhost:${port}`);
    });
    ```

    **この処理で行うこと:**

    * Auth0 のドメインと API オーディエンスを使用して、JWT 検証ミドルウェアを作成します
    * 受信したアクセストークンの `iss` および `aud` クレームを検証します
    * 個々のルートを保護するために `checkJwt` を利用できるようにします
  </Step>

  <Step title="API ルートを作成" stepNumber={5}>
    `server.js` にパブリックルートと保護されたルートを追加します。

    ```javascript server.js expandable lines theme={null}
    require('dotenv').config();
    const express = require('express');
    const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');

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

    // JWT検証ミドルウェアの設定
    const checkJwt = auth({
      issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
      audience: process.env.AUTH0_AUDIENCE,
    });

    // パブリックルート - 認証不要
    app.get('/api/public', (req, res) => {
      res.json({
        message: 'Hello from a public endpoint! You don\'t need to be authenticated to see this.',
        timestamp: new Date().toISOString(),
      });
    });

    // 保護されたルート - 有効なアクセストークンが必要
    app.get('/api/private', checkJwt, (req, res) => {
      res.json({
        message: 'Hello from a protected endpoint! You successfully authenticated.',
        user: req.auth.payload.sub,
        timestamp: new Date().toISOString(),
      });
    });

    // スコープ付き保護ルート - 'read:messages' スコープが必要
    app.get('/api/private-scoped', checkJwt, requiredScopes('read:messages'), (req, res) => {
      res.json({
        message: 'Hello from a scoped endpoint! You have the required permission.',
        user: req.auth.payload.sub,
        scope: req.auth.payload.scope,
        timestamp: new Date().toISOString(),
      });
    });

    // エラー処理ミドルウェア
    app.use((err, req, res, next) => {
      const status = err.status || 500;
      const message = err.message || 'Internal Server Error';

      res.status(status).json({
        error: err.code || 'server_error',
        message: status === 401 ? 'Authentication required' : message,
      });
    });

    // サーバーの起動
    app.listen(port, () => {
      console.log(`API server running at http://localhost:${port}`);
    });
    ```

    **要点:**

    * パブリックルートでは認証は不要です
    * 保護されたルートでは、有効な JWT を要求するために `checkJwt` ミドルウェアを使用します
    * スコープ付きルートでは、トークン内の特定の権限を要求するために `requiredScopes()` を使用します
    * `req.auth.payload` には、認証済みリクエストのデコードされた JWT クレームが含まれます
    * `sub` クレームには、ユーザーの一意の識別子が含まれます
  </Step>

  <Step title="API を起動する" stepNumber={6}>
    開発サーバーを起動します:

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

    API は [http://localhost:3001](http://localhost:3001) で実行されています。

    <Info>
      Node.js 18 以降では、`--watch` フラグを使用すると、ファイルの変更時にサーバーが自動的に再起動します。
    </Info>
  </Step>

  <Step title="APIをテストする" stepNumber={7}>
    公開エンドポイントをテストします (認証は不要です) :

    ```bash theme={null}
    curl http://localhost:3001/api/public
    ```

    以下のように表示されます:

    ```json theme={null}
    {
      "message": "Hello from a public endpoint! You don't need to be authenticated to see this.",
      "timestamp": "2024-01-15T10:30:00.000Z"
    }
    ```

    トークンなしで保護されたエンドポイントをテストします (失敗するはずです) :

    ```bash theme={null}
    curl http://localhost:3001/api/private
    ```

    401 Unauthorized エラーが表示されるはずです。

    ```json theme={null}
    {
      "error": "unauthorized",
      "message": "Authentication required"
    }
    ```

    有効なトークンでテストするには、次の手順に従います。

    1. [Auth0 Dashboard](https://manage.auth0.com/) → **Applications** → **APIs** に移動します
    2. 対象の API を選択し、**Test** タブを開きます
    3. 生成されたアクセストークンをコピーします

    保護されたエンドポイントをテストします。

    ```bash theme={null}
    curl http://localhost:3001/api/private \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
    ```

    以下が表示されます:

    ```json theme={null}
    {
      "message": "Hello from a protected endpoint! You successfully authenticated.",
      "user": "auth0|abc123...",
      "timestamp": "2024-01-15T10:30:00.000Z"
    }
    ```
  </Step>
</Steps>

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

  これで、保護された API が用意できているはずです。API は次のとおりです。

  1. 認証なしでパブリックエンドポイントへのリクエストを受け付ける
  2. 有効なトークンなしで保護されたエンドポイントへのリクエストを拒否する
  3. JWT トークンを Auth0 のドメインと対象者に照らして検証する
  4. `req.auth.payload` を通じて、トークンのクレームに含まれるユーザー情報を提供する
</Check>

***

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

<Accordion title="スコープベースの認可">
  スコープを使用すると、きめ細かなアクセス制御を実現できます。エンドポイントごとに必要なスコープを指定できます。

  **Auth0 でスコープを設定する:**

  1. [Auth0 Dashboard](https://manage.auth0.com/) で **Applications** → **APIs** → 対象の API の順に移動します
  2. **Permissions** タブを開きます
  3. `read:messages`、`write:messages`、`admin:access` などの権限を追加します

  **スコープでルートを保護する:**

  ```javascript server.js theme={null}
  const { auth, requiredScopes } = require('express-oauth2-jwt-bearer');

  // 'read:messages' スコープが必要
  app.get('/api/messages', checkJwt, requiredScopes('read:messages'), (req, res) => {
    res.json({
      messages: [
        { id: 1, text: 'Hello!' },
        { id: 2, text: 'World!' },
      ],
    });
  });

  // 'admin:access' スコープが必要
  app.get('/api/admin', checkJwt, requiredScopes('admin:access'), (req, res) => {
    res.json({
      message: 'Admin access granted',
      userId: req.auth.payload.sub,
    });
  });
  ```

  <Note>
    リクエストに必要なスコープが含まれていない場合、API は `insufficient_scope` エラーとともに `403 Forbidden` を返します。アクセストークンを取得する際に、クライアントアプリケーションが正しいスコープを要求するようにしてください。
  </Note>
</Accordion>

<Accordion title="カスタムクレームの検証">
  スコープに加えて、JWT ペイロード内のカスタムクレームも検証できます。

  ```javascript server.js theme={null}
  const { auth, claimEquals, claimIncludes, claimCheck } = require('express-oauth2-jwt-bearer');

  // クレーム値の完全一致を要求
  app.get('/api/org/:orgId',
    checkJwt,
    claimEquals('org_id', 'org_123'),
    (req, res) => {
      res.json({ message: 'Organization access granted' });
    }
  );

  // クレームに指定したすべての値が含まれていることを要求
  app.get('/api/roles',
    checkJwt,
    claimIncludes('roles', 'editor', 'viewer'),
    (req, res) => {
      res.json({ message: 'Role check passed' });
    }
  );

  // カスタムクレームの検証ロジック
  app.get('/api/premium',
    checkJwt,
    claimCheck((claims) => {
      return claims.subscription === 'premium' && claims.verified === true;
    }),
    (req, res) => {
      res.json({ message: 'Premium feature access granted' });
    }
  );
  ```

  <Note>
    カスタムクレームは、標準の OIDC クレームでない限り、名前空間付き URL (例: `https://myapp.com/roles`) を使用する必要があります。[カスタムクレームの詳細をご確認ください](https://auth0.com/docs/secure/tokens/json-web-tokens/create-custom-claims)。
  </Note>
</Accordion>

<Accordion title="任意の認証（公開/非公開ルートの混在）">
  同じルートで、認証済みアクセスと匿名アクセスの両方を許可できます。

  ```javascript server.js theme={null}
  const optionalAuth = auth({
    issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
    audience: process.env.AUTH0_AUDIENCE,
    authRequired: false,
  });

  app.get('/api/feed', optionalAuth, (req, res) => {
    if (req.auth) {
      res.json({
        message: `Welcome back, ${req.auth.payload.sub}!`,
        personalizedContent: true,
      });
    } else {
      res.json({
        message: 'Welcome, guest!',
        personalizedContent: false,
      });
    }
  });
  ```
</Accordion>

<Accordion title="CORS の設定">
  Web アプリケーションからのリクエストを許可するには、CORS を有効にします。

  ```bash theme={null}
  npm install cors
  ```

  ```javascript server.js theme={null}
  const cors = require('cors');

  app.use(cors({
    origin: ['http://localhost:3000', 'http://localhost:5173'],
    allowedHeaders: ['Authorization', 'Content-Type'],
    exposedHeaders: ['WWW-Authenticate'],
  }));
  ```

  本番環境では、正確なオリジンを指定してください。

  ```javascript server.js theme={null}
  app.use(cors({
    origin: [
      'https://myapp.com',
      'https://www.myapp.com'
    ],
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
  }));
  ```
</Accordion>

<Accordion title="カスタムエラー処理">
  認証エラーに対する包括的なエラー処理を追加します。

  ```javascript server.js theme={null}
  const { UnauthorizedError, InvalidTokenError, InsufficientScopeError } = require('express-oauth2-jwt-bearer');

  app.use((err, req, res, next) => {
    if (err instanceof InsufficientScopeError) {
      return res.status(403).json({
        error: 'forbidden',
        message: 'You do not have permission to access this resource',
        required_scopes: err.requiredScopes,
      });
    }

    if (err instanceof InvalidTokenError) {
      return res.status(401).json({
        error: 'invalid_token',
        message: 'The provided token is invalid or expired',
      });
    }

    if (err instanceof UnauthorizedError) {
      return res.status(401).set(err.headers).json({
        error: 'unauthorized',
        message: 'Authentication required',
      });
    }

    next(err);
  });
  ```
</Accordion>

<Accordion title="TypeScriptサポート">
  TypeScript プロジェクトでは、型定義をインストールしてプロジェクトを設定します。

  ```bash theme={null}
  npm install -D typescript @types/express @types/node
  ```

  `server.ts` を作成します。

  ```typescript server.ts theme={null}
  import 'dotenv/config';
  import express, { Request, Response, NextFunction } from 'express';
  import { auth, requiredScopes, UnauthorizedError } from 'express-oauth2-jwt-bearer';

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

  const checkJwt = auth({
    issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
    audience: process.env.AUTH0_AUDIENCE,
  });

  app.get('/api/public', (req: Request, res: Response) => {
    res.json({ message: 'Public endpoint - no authentication required' });
  });

  app.get('/api/private', checkJwt, (req: Request, res: Response) => {
    res.json({
      message: 'Private endpoint',
      user: req.auth?.payload.sub,
    });
  });

  app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
    if (err instanceof UnauthorizedError) {
      res.status(err.status).set(err.headers).json({
        error: err.code || 'unauthorized',
        message: 'Authentication required',
      });
    } else {
      res.status(500).json({
        error: 'server_error',
        message: 'Internal Server Error',
      });
    }
  });

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

  `tsconfig.json` を追加します。

  ```json tsconfig.json theme={null}
  {
    "compilerOptions": {
      "target": "ES2020",
      "module": "commonjs",
      "strict": true,
      "esModuleInterop": true,
      "skipLibCheck": true,
      "outDir": "./dist"
    },
    "include": ["*.ts"]
  }
  ```

  次のコマンドで実行します: `npx ts-node server.ts`
</Accordion>

***

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

<AccordionGroup>
  <Accordion title="よくある問題と解決策">
    ### 「認可トークンが見つかりませんでした」

    **問題:** API がリクエスト内のアクセストークンを見つけられません。

    **解決策:**

    1. `Authorization` ヘッダーが含まれていることを確認します: `Authorization: Bearer YOUR_TOKEN`
    2. トークンの前に `Bearer` が含まれていることを確認します
    3. トークンの有効期限が切れていないことを確認します

    ### 「無効なトークン」または「jwt malformed」

    **問題:** トークンの形式が無効です。

    **解決策:**

    1. **アクセストークン** を使用していることを確認します。IDトークンではありません
    2. トークンは API の `audience` パラメーターを指定して取得する必要があります
    3. トークンが有効な JWT であることを確認します (ドット区切りの 3 つの部分で構成されている必要があります)

    ### 想定外の「iss」または「aud」の値

    **問題:** トークン内の Issuer または 対象者 が設定と一致していません。

    **解決策:**

    1. [jwt.io](https://jwt.io) でトークンをデコードします
    2. `iss` クレーム が `https://YOUR_AUTH0_DOMAIN/` と一致することを確認します (末尾のスラッシュに注意)
    3. `aud` クレーム が `AUTH0_AUDIENCE` と完全に一致することを確認します
    4. `.env` の値を確認します:

    ```bash theme={null}
    AUTH0_DOMAIN=dev-abc123.us.auth0.com
    AUTH0_AUDIENCE=https://my-express-api.example.com
    ```

    ### 「You must provide an issuerBaseURL」または「audience is required」

    **問題:** 環境変数が読み込まれていません。

    **解決策:**

    1. `.env` ファイルがプロジェクトのルートに存在することを確認します
    2. `dotenv` がインストールされていることを確認します: `npm install dotenv`
    3. サーバーファイルの先頭に `require('dotenv').config()` を追加します
    4. 変数名が完全に一致していることを確認します (大文字と小文字は区別されます)

    ### すべてのリクエストで 401 Unauthorized が返る

    **考えられる原因:**

    * トークンの有効期限が切れている
    * 対象者 が一致していない
    * Issuer が一致していない

    **デバッグ手順:**

    1. [jwt.io](https://jwt.io) でトークンをデコードします
    2. `exp` クレーム の期限が過ぎていないことを確認します
    3. `aud` クレーム が `AUTH0_AUDIENCE` と完全に一致することを確認します
    4. `iss` クレーム が `https://{AUTH0_DOMAIN}/` であることを確認します
    5. `Authorization` ヘッダーの形式が `Bearer YOUR_TOKEN` であることを確認します (間にスペースが必要です)

    ### 「insufficient\_scope」で 403 Forbidden が返る

    **問題:** トークンに必要なスコープが含まれていません。

    **解決策:**

    1. 必要なスコープが Auth0 API で定義されていることを確認します (Dashboard → **Applications** → **APIs** → **Permissions**)
    2. トークン取得時に必要なスコープをリクエストします
    3. トークンの `scope` クレーム に必要なスコープが含まれていることを確認します

    ### ブラウザーでの CORS エラー

    **問題:** CORS ポリシーにより、ブラウザーが API リクエストをブロックしています。

    **解決策:** `cors` をインストールして設定します:

    ```bash theme={null}
    npm install cors
    ```

    ```javascript theme={null}
    const cors = require('cors');

    app.use(cors({
      origin: 'http://localhost:3000',
    }));
    ```
  </Accordion>
</AccordionGroup>

***

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

保護されたAPIを用意できたら、次の内容も確認してください。

* **[ロールベースアクセス制御](https://auth0.com/docs/manage-users/access-control/rbac)** - きめ細かな権限を実装する
* **[API 認可のベストプラクティス](https://auth0.com/docs/secure/tokens/access-tokens)** - アクセストークンのベストプラクティスを確認する
* **[API を監視する](https://auth0.com/docs/deploy-monitor/logs)** - ログ記録と監視を設定する
* **[Auth0 Community](https://community.auth0.com/)** - コミュニティでサポートを得る

***

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

* **[express-oauth2-jwt-bearer GitHub](https://github.com/auth0/node-oauth2-jwt-bearer/tree/main/packages/express-oauth2-jwt-bearer)** - ソースコードと使用例
* **[Express.js Documentation](https://expressjs.com/)** - Express の詳細情報
* **[Auth0 API Authentication](https://auth0.com/docs/secure/tokens/access-tokens)** - アクセストークンについて詳しく理解する
* **[JWT.io](https://jwt.io/)** - JWT のデバッグとデコード
