> ## 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 />

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

<Accordion title="AI を使って Auth0 を統合する" icon="microchip-ai" iconType="solid" defaultOpen>
  Claude Code、Cursor、GitHub Copilot などの AI coding assistant を使っている場合は、[Agent Skills](https://agentskills.io/home) を利用して、数分で Auth0 API のauthenticationを自動的に追加できます。

  **インストール:**

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

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

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

  AI アシスタントが、Auth0 API の作成、資格情報の取得、`express-oauth2-jwt-bearer` のインストール、JWT ミドルウェアの設定、トークンの検証による API エンドポイントの保護を自動的に行います。[Agent Skills の完全なドキュメント →](/docs/ja-jp/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` に start スクリプトを追加します:

    ```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 コマンドを使う方法と、Auth0 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. 指定した identifier で Auth0 API を作成します
          3. ドメインや identifier を含む 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. **アプリケーション** → **APIs** → **Create API** の順に進みます
        3. API の名前を入力します (例: "My Express API")
        4. **Identifier** を設定します (例: `https://my-express-api.example.com`)
           * これは API の audience であり、有効な URL 形式である必要があります
           * 実在する URL である必要はなく、単なる識別子です
        5. **Signing Algorithm** は **RS256** のままにします
        6. **Create** をクリックします
        7. **設定** タブから **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` はダッシュボード上の 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 audience を使って 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}`);
    });
    ```

    **要点:**

    * Public routes では認証は不要です
    * Protected routes では、有効な JWT を必須にするために `checkJwt` ミドルウェアを使用します
    * Scoped routes では、トークン内の特定の権限を必須にするために `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"
    }
    ```

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

    ```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/) → **アプリケーション** → **APIs** に移動します
    2. API を選択して → **Test** タブを開きます
    3. 生成された access token をコピーします

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

    ```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 ドメインと audience に照らして検証する
  4. `req.auth.payload` を通じて、トークンのクレームからユーザー情報を取得できる
</Check>

***

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

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

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

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

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

  ```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>
    リクエストに必要な scope が含まれていない場合、API は `insufficient_scope` エラーとともに `403 Forbidden` を返します。access token の取得時に、クライアントアプリケーションが正しいスコープを request していることを確認してください。
  </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="よくある問題と解決方法">
    ### 「No authorization token was found」

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

    **解決方法:**

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

    ### 「Invalid token」または「jwt malformed」

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

    **解決方法:**

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

    ### 予期しない「iss」または「aud」の値

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

    **解決方法:**

    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 が発生する

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

    * トークンの有効期限が切れている
    * audience が一致していない
    * 発行者が一致していない

    **デバッグ手順:**

    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 に定義されていることを確認します (Auth0 Dashboard → **アプリケーション** → **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 認可 Best Practices](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 のデバッグとデコード
