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

> このガイドでは、Auth0 Fastify API SDK を使用して、JWT アクセストークンを使って Fastify の API エンドポイントを保護する方法を説明します。

# Fastify 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 Authentication を自動的に追加できます。

  **インストール:**

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

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

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

  AI アシスタントが、Auth0 API の作成、資格情報の取得、`@auth0/auth0-fastify-api` のインストール、プラグインの設定、JWT バリデーションによる API エンドポイントの保護まで自動的に行います。[agent skills の完全なドキュメント →](/docs/ja-jp/quickstart/agent-skills)
</Accordion>

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

  * **[Node.js](https://nodejs.org/en/download)** 20 LTS 以降
  * **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 10 以降、または **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22 以降、または **[pnpm](https://pnpm.io/installation)** 8 以降

  インストールの確認: `node --version && npm --version`

  **Fastify のバージョン互換性:** この クイックスタート は **Fastify 5.x** 以降で動作します。
</Note>

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

このクイックスタートでは、JWT アクセストークンを使って Fastify の API エンドポイントを保護する方法を紹介します。Auth0 アクセストークンを検証し、保護されたリソースへのアクセスを許可する安全な API を構築します。

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

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

    プロジェクトを初期化する

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

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

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

  <Step title="Auth0 Fastify API SDKをインストールする" stepNumber={2}>
    必要な依存パッケージをインストールする

    ```shellscript theme={null}
    npm install @auth0/auth0-fastify-api fastify dotenv
    ```

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

    ```json package.json theme={null}
    {
      "name": "auth0-fastify-api",
      "version": "1.0.0",
      "type": "module",
      "main": "server.js",
      "scripts": {
        "start": "node server.js",
        "dev": "node --watch server.js"
      },
      "dependencies": {
        "@auth0/auth0-fastify-api": "^1.2.0",
        "dotenv": "^16.3.1",
        "fastify": "^5.0.0"
      }
    }
    ```
  </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 Fastify API" \
            --identifier https://my-fastify-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 Fastify API" `
            --identifier https://my-fastify-api.example.com
          ```
        </CodeGroup>

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

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

        <Note>
          このコマンドでは次のことが行われます。

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

      <Tab title="Dashboard">
        1. [Auth0 Dashboard](https://manage.auth0.com/dashboard/) に移動します
        2. **アプリケーション** → **APIs** → **Create API** の順に進みます
        3. API の名前を入力します (例: "My Fastify API")
        4. **Identifier** を設定します (例: `https://my-fastify-api.example.com`)
           * これは API の audience であり、有効な URL 形式である必要があります
           * 実在する URL である必要はなく、単なる identifier です
        5. **Signing Algorithm** は **RS256** のままにします
        6. **Create** をクリックします
        7. **設定** タブから **Identifier** の値をコピーします

        次の値を含む `.env` ファイルを作成します。

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

        <Warning>
          `YOUR_AUTH0_DOMAIN` は Auth0 テナントのドメイン (例: `dev-abc123.us.auth0.com`) に、`YOUR_API_IDENTIFIER` はダッシュボードの API identifier (例: `https://my-fastify-api.example.com`) に置き換えてください。
        </Warning>
      </Tab>
    </Tabs>

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

  <Step title="Auth0 APIプラグインを設定する" stepNumber={4}>
    Fastifyサーバーを作成し、Auth0 API プラグインを登録します:

    ```javascript server.js {1-3,6-7,10-13,16-17} lines theme={null}
    import 'dotenv/config';
    import Fastify from 'fastify';
    import fastifyAuth0Api from '@auth0/auth0-fastify-api';

    const fastify = Fastify({ logger: true });
    const port = process.env.PORT || 3001;

    // Auth0 API プラグインを登録する
    await fastify.register(fastifyAuth0Api, {
      domain: process.env.AUTH0_DOMAIN,
      audience: process.env.AUTH0_AUDIENCE,
    });

    // サーバーを起動する
    fastify.listen({ port }, (err) => {
      if (err) {
        fastify.log.error(err);
        process.exit(1);
      }
      fastify.log.info(`API server running at http://localhost:${port}`);
    });
    ```

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

    * Auth0 APIプラグインを、Auth0 domain と API audience を使って登録します
    * 受信リクエストに対する JWT のバリデーションを設定します
    * ルートを保護するための `requireAuth()` preHandler を利用できるようにします
  </Step>

  <Step title="APIルートを作成する" stepNumber={5}>
    `server.js` に公開ルートと保護ルートを追加します:

    ```javascript server.js expandable lines theme={null}
    import 'dotenv/config';
    import Fastify from 'fastify';
    import fastifyAuth0Api from '@auth0/auth0-fastify-api';

    const fastify = Fastify({ logger: true });
    const port = process.env.PORT || 3001;

    // Auth0 APIプラグインを登録
    await fastify.register(fastifyAuth0Api, {
      domain: process.env.AUTH0_DOMAIN,
      audience: process.env.AUTH0_AUDIENCE,
    });

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

    // 保護されたルート - 有効なアクセストークンが必要
    fastify.get('/api/private', {
      preHandler: fastify.requireAuth()
    }, async (request, reply) => {
      return {
        message: 'Hello from a protected endpoint! You successfully authenticated.',
        user: request.user.sub,
        timestamp: new Date().toISOString(),
      };
    });

    // 保護されたルート - トークンからユーザー情報を返す
    fastify.get('/api/profile', {
      preHandler: fastify.requireAuth()
    }, async (request, reply) => {
      return {
        message: 'Your user profile from the access token',
        profile: request.user,
      };
    });

    // サーバーを起動
    fastify.listen({ port }, (err) => {
      if (err) {
        fastify.log.error(err);
        process.exit(1);
      }
      fastify.log.info(`API server running at http://localhost:${port}`);
    });
    ```

    **重要なポイント:**

    * 公開ルートでは認証は不要です
    * 保護されたルートでは、有効な JWT を必須にするために `preHandler: fastify.requireAuth()` を使用します
    * `request.user` には、認証済みリクエストのデコード済み JWT クレームが含まれます
    * `sub` クレームには、ユーザーの一意の識別子が含まれます
  </Step>

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

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

    API は現在、[http://localhost:3001](http://localhost:3001) で動作しています。

    <Info>
      Node.js 20+ の `--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": "No authorization token was found"
    }
    ```

    有効な token でテストするには、次の手順を行います。

    1. ユーザーを認証するクライアントアプリケーション (Web またはモバイルアプリ) を作成します
    2. クライアントが API 用の access token を request するように設定します (audience パラメーターを使用)
    3. その access token を Authorization header で使用します

    token を使用する例:

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

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

  これで、保護された API が用意できているはずです。API は次のように動作します。

  1. 認証なしで公開エンドポイントへのリクエストを受け付ける
  2. 有効なトークンなしで保護されたエンドポイントへのリクエストを拒否する
  3. JWT トークンを Auth0 ドメインと audience に対して検証する
  4. トークンのクレームから `request.user` 経由でユーザー情報を提供する
</Check>

***

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

<Accordion title="TypeScriptでカスタムトークンのクレームを扱う">
  Token インターフェースを拡張して、アクセストークン内のカスタムクレームに型安全性を持たせることができます。

  ```typescript server.ts theme={null}
  import '@auth0/auth0-fastify-api';

  // カスタムクレームを追加して Token インターフェースを拡張
  declare module '@auth0/auth0-fastify-api' {
    interface Token {
      sub: string;
      permissions?: string[];
      'https://myapp.com/roles'?: string[];
      email?: string;
      email_verified?: boolean;
    }
  }
  ```

  これで、TypeScript がカスタムクレームを認識するようになります。

  ```typescript server.ts theme={null}
  fastify.get('/api/profile', {
    preHandler: fastify.requireAuth()
  }, async (request, reply) => {
    // TypeScript がこれらのプロパティを認識
    const userRoles = request.user['https://myapp.com/roles']; // string[] | undefined
    const permissions = request.user.permissions; // string[] | undefined
    const email = request.user.email; // string | undefined

    return {
      userId: request.user.sub,
      roles: userRoles || [],
      permissions: permissions || [],
      email: email,
    };
  });
  ```

  <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}
  // 特定の権限を確認するミドルウェア
  function requirePermission(permission) {
    return async (request, reply) => {
      const permissions = request.user.permissions || [];

      if (!permissions.includes(permission)) {
        return reply.status(403).send({
          error: 'Forbidden',
          message: `Missing required permission: ${permission}`
        });
      }
    };
  }

  // 'read:messages' 権限が必要なルート
  fastify.get('/api/messages', {
    preHandler: [
      fastify.requireAuth(),
      requirePermission('read:messages')
    ]
  }, async (request, reply) => {
    return {
      messages: ['Message 1', 'Message 2', 'Message 3']
    };
  });

  // 'write:messages' 権限が必要なルート
  fastify.post('/api/messages', {
    preHandler: [
      fastify.requireAuth(),
      requirePermission('write:messages')
    ]
  }, async (request, reply) => {
    return {
      message: 'Message created successfully',
      id: 'msg_123'
    };
  });
  ```

  <Note>
    権限は Auth0 API の設定で構成し、クライアントに付与する必要があります。[API 権限の詳細](https://auth0.com/docs/manage-users/access-control/configure-core-rbac/rbac-users/assign-permissions-users)をご覧ください。
  </Note>
</Accordion>

<Accordion title="ロールベースの認可">
  カスタムクレームを使用して、ロールベースのアクセス制御を実装します。

  ```javascript server.js theme={null}
  // 特定のロールを確認するミドルウェア
  function requireRole(role) {
    return async (request, reply) => {
      const roles = request.user['https://myapp.com/roles'] || [];

      if (!roles.includes(role)) {
        return reply.status(403).send({
          error: 'Forbidden',
          message: `Missing required role: ${role}`
        });
      }
    };
  }

  // Admin 専用ルート
  fastify.get('/api/admin/users', {
    preHandler: [
      fastify.requireAuth(),
      requireRole('admin')
    ]
  }, async (request, reply) => {
    return {
      users: [
        { id: 1, name: 'User 1' },
        { id: 2, name: 'User 2' }
      ]
    };
  });

  // manager または admin 用ルート
  function requireAnyRole(...roles) {
    return async (request, reply) => {
      const userRoles = request.user['https://myapp.com/roles'] || [];
      const hasRole = roles.some(role => userRoles.includes(role));

      if (!hasRole) {
        return reply.status(403).send({
          error: 'Forbidden',
          message: `Missing required role. Need one of: ${roles.join(', ')}`
        });
      }
    };
  }

  fastify.get('/api/reports', {
    preHandler: [
      fastify.requireAuth(),
      requireAnyRole('admin', 'manager')
    ]
  }, async (request, reply) => {
    return { reports: [] };
  });
  ```

  <Note>
    ロールは 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="CORS 設定">
  Web アプリケーションからのリクエストを許可するには、CORS を有効にします。

  ```bash theme={null}
  npm install @fastify/cors
  ```

  ```javascript server.js theme={null}
  import cors from '@fastify/cors';

  await fastify.register(cors, {
    origin: ['http://localhost:3000', 'http://localhost:5173'], // Web アプリケーションの URL
    credentials: true,
  });
  ```

  本番環境では、明示的にオリジンを指定します。

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

<Accordion title="エラーハンドリング">
  認証エラーに対応する包括的なエラーハンドリングを追加します。

  ```javascript server.js theme={null}
  // カスタムエラーハンドラー
  fastify.setErrorHandler((error, request, reply) => {
    fastify.log.error(error);

    // JWT のバリデーションエラーを処理
    if (error.statusCode === 401) {
      return reply.status(401).send({
        error: 'Unauthorized',
        message: error.message || 'Invalid or missing access token',
        code: 'UNAUTHORIZED'
      });
    }

    // 権限/ロールのエラーを処理
    if (error.statusCode === 403) {
      return reply.status(403).send({
        error: 'Forbidden',
        message: error.message || 'Insufficient permissions',
        code: 'FORBIDDEN'
      });
    }

    // その他のエラーを処理
    return reply.status(error.statusCode || 500).send({
      error: 'Internal Server Error',
      message: 'An unexpected error occurred',
      code: 'INTERNAL_ERROR'
    });
  });

  // 未定義ルートのハンドラー
  fastify.setNotFoundHandler((request, reply) => {
    return reply.status(404).send({
      error: 'Not Found',
      message: `Route ${request.method} ${request.url} not found`,
      code: 'NOT_FOUND'
    });
  });
  ```
</Accordion>

<Accordion title="レート制限">
  レート制限を使って、APIを不正利用から保護できます。

  ```bash theme={null}
  npm install @fastify/rate-limit
  ```

  ```javascript server.js theme={null}
  import rateLimit from '@fastify/rate-limit';

  await fastify.register(rateLimit, {
    max: 100, // 最大リクエスト数
    timeWindow: '1 minute', // 時間枠
    errorResponseBuilder: (request, context) => {
      return {
        error: 'Too Many Requests',
        message: `Rate limit exceeded. Try again in ${context.after}`,
        retryAfter: context.after
      };
    }
  });

  // 特定のルートに、より厳しい制限を適用
  fastify.get('/api/expensive-operation', {
    preHandler: fastify.requireAuth(),
    config: {
      rateLimit: {
        max: 10,
        timeWindow: '1 minute'
      }
    }
  }, async (request, reply) => {
    return { result: 'expensive operation result' };
  });
  ```
</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 つの部分がある必要があります)

    ### 「無効な署名」

    **問題:** トークンの署名が一致しません。

    **解決策:**

    1. `AUTH0_DOMAIN` がトークンを発行したドメインと一致していることを確認します
    2. RS256 署名アルゴリズム (デフォルト) を使用していることを確認します
    3. トークンが改変されていないことを確認します

    ### 「無効なaudience」

    **問題:** トークンの audience が API と一致しません。

    **解決策:** クライアントアプリケーションは、正しい audience を指定してトークンをリクエストする必要があります:

    ```javascript theme={null}
    // クライアントアプリ内
    const token = await getAccessTokenSilently({
      authorizationParams: {
        audience: 'https://my-fastify-api.example.com' // API 識別子と一致する必要があります
      }
    });
    ```

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

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

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

    ```bash theme={null}
    npm install @fastify/cors
    ```

    ```javascript theme={null}
    import cors from '@fastify/cors';

    await fastify.register(cors, {
      origin: 'http://localhost:3000', // フロントエンドの URL
      credentials: true
    });
    ```
  </Accordion>
</AccordionGroup>

***

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

保護されたAPIを用意できたので、次の項目もあわせて確認してみてください。

* **[Fastify Web App クイックスタート](/docs/ja-jp/quickstart/webapp/fastify)** - APIを呼び出すWeb アプリケーションを構築する
* **[ロールベースのアクセス制御](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)** - ログと監視を設定する

***

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

* **[auth0-fastify-api GitHub](https://github.com/auth0/auth0-fastify/tree/main/packages/auth0-fastify-api)** - ソースコードとサンプル
* **[Fastify Documentation](https://fastify.dev/)** - Fastify の詳細はこちら
* **[Auth0 API Authentication](https://auth0.com/docs/secure/tokens/access-tokens)** - アクセストークンについて理解する
* **[Auth0 Community](https://community.auth0.com/)** - Community でサポートを受ける
