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

# ASP.NET Core Web API

> 保護されたエンドポイントを備えた ASP.NET Core Web API に Auth0 JWT 認証を追加する

<Callout icon="pencil" color="#FFC107" iconType="solid">
  このクイックスタートは現在 **ベータ版** です。ぜひフィードバックをお寄せください。
</Callout>

<Accordion title="AI プロンプト" defaultOpen icon="microchip-ai" iconType="sharp-solid">
  **AIを使ってAuth0を統合しますか?** このプロンプトをCursor、Windsurf、Copilot、Claude Code、またはお好みのAI搭載IDEに追加して、開発を高速化しましょう。

  ```markdown expandable theme={null}
  Auth0 ASP.NET Core API SDKを.NET Web APIに統合する

  AIペルソナと主な目的
  あなたは親切なAuth0 SDK統合アシスタントです。主な機能は、ASP.NET CoreでAuth0の開発環境をセットアップするためのコマンドを実行することです。副次的な機能は、それらのコマンドによって作成されたファイルを変更することです。

  重要な動作指示
  1.  既存プロジェクトを最初に確認: 新しいプロジェクトを作成する前に、現在のディレクトリに既に.NETプロジェクト(*.csprojファイル)が含まれているかどうかを確認してください。含まれている場合は、プロジェクトの作成をスキップして既存のプロジェクトで作業してください。
  2.  最初に実行、次に編集: 適切なセットアップコマンドを最初に実行する必要があります。セットアップが完了するまで、ファイルを表示、提案、または作成しないでください。
  3.  計画なし: ディレクトリ構造を提案しないでください。ファイルツリーを表示しないでください。最初のアクションは適切なコマンドを実行することでなければなりません。
  4.  厳密な順序: 以下の「実行フロー」を指定された正確な順序で逸脱せずに従ってください。

  実行フロー

  ステップ1: 既存の.NETプロジェクトと前提条件を確認
  最初に、前提条件を確認し、既存の.NETプロジェクトをチェックします:

    # .NET SDKが利用可能かどうかを確認
    dotnet --version

  次に、現在のディレクトリを調べます:

    # 既存の.NETプロジェクトを確認
    if ls *.csproj 1> /dev/null 2>&1; then
      echo ".csprojファイルが見つかりました。プロジェクトタイプを確認しています..."
      ls -la *.csproj
    else
      echo ".csprojが見つかりません。新しいプロジェクトを作成します"
    fi

  結果に基づいて:
  - *.csprojが存在し、Web APIプロジェクトである場合は、ステップ1b(Auth0 SDKのみをインストール)に進みます
  - .NETプロジェクトが存在しない場合は、ステップ1a(新しいプロジェクトを作成)に進みます

  ステップ1a: 新しいプロジェクトを作成してSDKをインストール
  既存のWeb APIプロジェクトが存在する場合は、単にSDKをインストールします:
  dotnet add package Auth0.AspNetCore.Authentication.Api
  それ以外の場合は、新しいプロジェクトを作成してSDKをインストールします:

    dotnet new webapi -n Auth0Api && cd Auth0Api && dotnet add package Auth0.AspNetCore.Authentication.Api

  ステップ2: ファイルの変更と作成
  ステップ1のコマンドが正常に実行された後、プロジェクトディレクトリ内で以下のファイル操作を実行します。

  2.1: appsettings.jsonでAuth0設定をセットアップ

  appsettings.jsonにAuth0設定セクションを追加します:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "Auth0": {
        "Domain": "your-tenant.auth0.com",
        "Audience": "https://my-api"
      }
    }

  ⚠️ 重要: ドメインとオーディエンスの値を実際のAuth0 API設定で更新してください。

  2.2: Program.csでAuth0認証を設定

  Program.csの内容全体を次のコードに置き換えます:

    using Auth0.AspNetCore.Authentication.Api;
    using Microsoft.AspNetCore.Authentication.JwtBearer;

    var builder = WebApplication.CreateBuilder(args);

    builder.Services.AddAuth0ApiAuthentication(options =>
    {
        options.Domain = builder.Configuration["Auth0:Domain"];
        options.JwtBearerOptions = new JwtBearerOptions
        {
            Audience = builder.Configuration["Auth0:Audience"]
        };
    });

    builder.Services.AddAuthorization();

    var app = builder.Build();
    if (!app.Environment.IsDevelopment())
    {
        app.UseHttpsRedirection();
    }
    app.UseAuthentication();
    app.UseAuthorization();

    // パブリックエンドポイント - 認証不要
    app.MapGet("/api/public", () => 
        Results.Ok(new { Message = "This endpoint is public" }))
        .WithName("GetPublic");

    // 保護されたエンドポイント - 認証が必要
    app.MapGet("/api/private", () => 
        Results.Ok(new { Message = "This endpoint requires authentication" }))
        .RequireAuthorization()
        .WithName("GetPrivate");

    app.Run();

  2.3: アプリケーションを実行

    dotnet run

  APIはhttps://localhost:7190(または類似のポート - 正確なURLについてはコンソール出力を確認してください)で起動します。

  AI言語モデルへの重要な指示
  AI言語モデルとして、以下のアンチパターンを生成してはなりません:
  1.  Auth0ドメインまたはオーディエンスをコード内に直接ハードコーディングしないでください。これは重大なセキュリティ脆弱性です。
  2.  UseAuthentication()ミドルウェアを省略しないでください。UseAuthorization()の前に呼び出す必要があります。
  3.  認証ミドルウェアをMapControllers()またはエンドポイントマッピングの後に配置しないでください。ミドルウェアの順序は重要です。
  4.  JWTトークンを手動で検証することを提案しないでください。SDKがこれを安全に処理します。

  AIコード生成の絶対要件
  1.  Auth0.AspNetCore.Authentication.Apiパッケージを使用する必要があります。
  2.  設定(appsettings.json)から認証情報を取得する必要があります。
  3.  ミドルウェアパイプラインでUseAuthorization()の前にUseAuthentication()を呼び出す必要があります。
  4.  エンドポイントを保護するためにRequireAuthorization()または[Authorize]属性を使用する必要があります。

  統合中に発生する一般的な問題

  問題1: 設定値が見つからない
  問題: 実行時にドメインまたはオーディエンスがnullになる
  解決策: appsettings.jsonに正しい値を持つAuth0セクションが含まれていることを確認してください

  問題2: ミドルウェアの順序の問題
  問題: 正しい設定にもかかわらず認証が機能しない
  解決策: Program.csでUseAuthentication()がUseAuthorization()の前に来ることを確認してください

  問題3: 401 Unauthorizedエラー
  問題: 有効なトークンが拒否される
  解決策: ドメインにhttps://が含まれていないこと、およびオーディエンスがAuth0 API識別子と正確に一致することを確認してください

  問題4: 開発環境でのHTTPS証明書エラー
  問題: ローカル実行時のSSL/TLSエラー
  解決策: `dotnet dev-certs https --trust`を実行して開発証明書を信頼してください
  ```
</Accordion>

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

  * **[.NET 8.0 ソフトウェア開発キット (SDK)](https://dotnet.microsoft.com/download/dotnet/8.0)** 以降
  * お好みの IDE (Visual Studio 2022、VS Code、または Rider)

  **.NET バージョン互換性:** このクイックスタートは **.NET 8.0** 以降に対応しています。
</Note>

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

このクイックスタートでは、ASP.NET Core Web API に Auth0 の JWT 認証機能を追加する方法を解説します。Auth0 ASP.NET Core API ソフトウェア開発キット (SDK) を使用して、保護されたエンドポイントを備えた安全な API を構築します。

<Steps>
  <Step title="新規プロジェクトを作成" stepNumber={1}>
    このクイックスタート用に新しい ASP.NET Core Web API プロジェクトを作成する

    ```bash theme={null}
    dotnet new webapi -n Auth0Api
    ```

    プロジェクトを開きます

    ```bash theme={null}
    cd Auth0Api
    ```
  </Step>

  <Step title="Auth0 ソフトウェア開発キット (SDK) をインストール" stepNumber={2}>
    ```bash theme={null}
    dotnet add package Auth0.AspNetCore.Authentication.Api
    ```
  </Step>

  <Step title="Auth0 API をセットアップする" stepNumber={3}>
    次に、Auth0 テナントで新しい API を作成し、その設定をプロジェクトに追加する必要があります。

    CLIコマンドを実行して自動的に実行するか、ダッシュボードから手動で実行するかを選択できます:

    <Tabs>
      <Tab title="CLI（コマンドラインインターフェース）">
        プロジェクトのルートディレクトリで次のシェル コマンドを実行して、Auth0 API を作成し、`appsettings.json` ファイルを更新してください。

        <Tabs>
          <Tab title="Mac/Linux">
            ```bash theme={null}
            AUTH0_API_NAME="My ASP.NET Core API" && \
            AUTH0_API_IDENTIFIER="https://my-api" && \
            brew tap auth0/auth0-cli && \
            brew install auth0 && \
            auth0 login --no-input && \
            auth0 apis create -n "${AUTH0_API_NAME}" -i "${AUTH0_API_IDENTIFIER}" --offline-access --token-lifetime 86400 --signing-alg RS256 --json > auth0-api-details.json && \
            DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && \
            AUDIENCE=$(jq -r '.identifier' auth0-api-details.json) && \
            jq --arg domain "$DOMAIN" --arg audience "$AUDIENCE" \
              '.Auth0.Domain = $domain | .Auth0.Audience = $audience' \
              appsettings.json > appsettings.tmp.json && \
            mv appsettings.tmp.json appsettings.json && \
            rm auth0-api-details.json && \
            echo "✅ appsettings.json updated with your Auth0 API details:" && \
            cat appsettings.json
            ```
          </Tab>

          <Tab title="Windows (PowerShell)">
            ```powershell theme={null}
            $ApiName = "My ASP.NET Core API"
            $ApiIdentifier = "https://my-api"
            $latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/auth0/auth0-cli/releases/latest"
            $latestVersion = $latestRelease.tag_name
            $version = $latestVersion -replace "^v"
            Invoke-WebRequest -Uri "https://github.com/auth0/auth0-cli/releases/download/${latestVersion}/auth0-cli_${version}_Windows_x86_64.zip" -OutFile ".\auth0.zip"
            Expand-Archive ".\auth0.zip" .\
            [System.Environment]::SetEnvironmentVariable('PATH', $Env:PATH + ";${pwd}")
            auth0 login --no-input
            auth0 apis create -n "$ApiName" -i "$ApiIdentifier" --offline-access --token-lifetime 86400 --signing-alg RS256 --json | Set-Content -Path auth0-api-details.json
            $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name
            $Audience = (Get-Content -Raw auth0-api-details.json | ConvertFrom-Json).identifier
            $Config = Get-Content -Raw appsettings.json | ConvertFrom-Json
            if (-not $Config.Auth0) { $Config | Add-Member -MemberType NoteProperty -Name Auth0 -Value @{} }
            $Config.Auth0.Domain = $Domain
            $Config.Auth0.Audience = $Audience
            $Config | ConvertTo-Json -Depth 10 | Set-Content appsettings.json
            Remove-Item auth0-api-details.json
            Write-Output "✅ appsettings.json updated with your Auth0 API details:"
            Get-Content appsettings.json
            ```
          </Tab>
        </Tabs>
      </Tab>

      <Tab title="ダッシュボード">
        作業を始める前に、`appsettings.json` ファイルに Auth0 の設定を追加してください

        ```json appsettings.json theme={null}
        {
          "Logging": {
            "LogLevel": {
              "Default": "Information",
              "Microsoft.AspNetCore": "Warning"
            }
          },
          "AllowedHosts": "*",
          "Auth0": {
            "Domain": "YOUR_AUTH0_DOMAIN",
            "Audience": "YOUR_AUTH0_API_IDENTIFIER"
          }
        }
        ```

        1. [Auth0 Dashboard](https://manage.auth0.com) → **Applications** → **APIs** に移動します
        2. **Create API** をクリックします
        3. API の詳細を入力します:
           * **Name**: My ASP.NET Core API
           * **Identifier**: `https://my-api` (これがオーディエンスになります)
           * **Signing Algorithm**: RS256
        4. **Create** をクリックします
        5. `appsettings.json` 内の `YOUR_AUTH0_DOMAIN` を、Test タブに表示されている **Domain** に置き換えます (例: `your-tenant.auth0.com`)
        6. `appsettings.json` 内の `YOUR_AUTH0_API_IDENTIFIER` を、**Identifier** に置き換えます (例: `https://my-api`)

        <Info>
          **Domain** には `https://` を含めないでください。ドメイン名のみを使用します (例: `your-tenant.auth0.com`)。

          **Audience** (API Identifier) は API のための一意の識別子であり、有効な URI であれば任意の値を使用できます。公開アクセス可能な URL である必要はありません。
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="認証を設定する" stepNumber={4}>
    `Program.cs` の内容をすべて、次のコードに置き換えてください。

    ```csharp Program.cs lines theme={null}
    using Auth0.AspNetCore.Authentication.Api;
    using Microsoft.AspNetCore.Authentication.JwtBearer;

    var builder = WebApplication.CreateBuilder(args);

    builder.Services.AddAuth0ApiAuthentication(options =>
    {
        options.Domain = builder.Configuration["Auth0:Domain"];
        options.JwtBearerOptions = new JwtBearerOptions
        {
            Audience = builder.Configuration["Auth0:Audience"]
        };
    });

    builder.Services.AddAuthorization();

    var app = builder.Build();

    if (!app.Environment.IsDevelopment())
    {
        app.UseHttpsRedirection();
    }

    app.UseAuthentication();
    app.UseAuthorization();

    app.Run();
    ```
  </Step>

  <Step title="公開エンドポイントと保護エンドポイントを作成する" stepNumber={5}>
    認証テスト用のエンドポイントを追加します。`Program.cs` の `app.Run()` の前に次のコードを追加します。

    ```csharp Program.cs theme={null}
    // パブリックエンドポイント - 認証不要
    app.MapGet("/api/public", () => 
        Results.Ok(new { Message = "This endpoint is public" }))
        .WithName("GetPublic");

    // 保護されたエンドポイント - 認証が必要
    app.MapGet("/api/private", () => 
        Results.Ok(new { Message = "This endpoint requires authentication" }))
        .RequireAuthorization()
        .WithName("GetPrivate");
    ```
  </Step>

  <Step title="API を起動する" stepNumber={6}>
    ```bash theme={null}
    dotnet run
    ```

    API は現在 `https://localhost:7190`（または類似の URL）で実行されています。正確な URL はコンソール出力を確認してください。
  </Step>
</Steps>

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

  これで、Auth0 で保護された正常に動作する API が、[localhost](https://localhost:7190/) 上で稼働しているはずです。
</Check>

***

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

<Accordion title="保護された API の呼び出し">
  アクセストークンを使用して保護されたエンドポイントをテストします。

  **1. アクセストークンを取得します。** Client Credentials フローを使用して Auth0 から取得します。

  ```bash theme={null}
  curl --request POST \
    --url https://YOUR_DOMAIN/oauth/token \
    --header 'content-type: application/json' \
    --data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"YOUR_AUDIENCE","grant_type":"client_credentials"}'
  ```

  <Info>
    `YOUR_CLIENT_ID` と `YOUR_CLIENT_SECRET` を取得するには、[Auth0 Dashboard](https://manage.auth0.com/#/applications) で Machine to Machine アプリケーションを作成し、対象の API に対して認可します。
  </Info>

  **2. パブリックエンドポイントをテストします**（200 OK が返るはずです）:

  ```bash theme={null}
  curl https://localhost:7190/api/public
  ```

  **3. 認証なしで保護されたエンドポイントをテストします**（401 Unauthorized が返るはずです）:

  ```bash theme={null}
  curl https://localhost:7190/api/private
  ```

  **4. トークンを使用して保護されたエンドポイントを呼び出します:**

  ```bash theme={null}
  curl https://localhost:7190/api/private \
    --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```
</Accordion>

<Accordion title="コントローラー ベースのエンドポイントの使用">
  大規模な API では、Minimal API のエンドポイントではなくコントローラーを使用します。

  **1. コントローラーのサポートを追加します:**

  ```csharp Program.cs theme={null}
  builder.Services.AddControllers();

  var app = builder.Build();

  if (!app.Environment.IsDevelopment())
  {
      app.UseHttpsRedirection();
  }

  app.UseAuthentication();
  app.UseAuthorization();

  app.MapControllers();

  app.Run();
  ```

  **2. コントローラーを作成します:**

  `Controllers/MessagesController.cs` を作成します。

  ```csharp Controllers/MessagesController.cs theme={null}
  using Microsoft.AspNetCore.Authorization;
  using Microsoft.AspNetCore.Mvc;

  namespace Auth0Api.Controllers;

  [ApiController]
  [Route("api/[controller]")]
  public class MessagesController : ControllerBase
  {
      [HttpGet]
      public IActionResult GetPublic()
      {
          return Ok(new { Message = "This endpoint is public" });
      }

      [Authorize]
      [HttpGet("private")]
      public IActionResult GetPrivate()
      {
          var userId = User.FindFirst("sub")?.Value;
          return Ok(new { Message = "This endpoint is protected", UserId = userId });
      }

      [Authorize(Policy = "read:messages")]
      [HttpGet("messages")]
      public IActionResult GetMessages()
      {
          return Ok(new { Messages = new[] { "Message 1", "Message 2" } });
      }
  }
  ```
</Accordion>

<Accordion title="スコープベースの認可によるルートの保護">
  アクセストークン内の特定のスコープに基づいてエンドポイントを保護します。

  **1. Auth0 の API でスコープを定義します:**

  [Auth0 Dashboard](https://manage.auth0.com) → APIs → 対象の API → Permissions で、次のスコープを追加します。

  * `read:messages` - メッセージの読み取り
  * `write:messages` - メッセージの書き込み

  **2. 認可ポリシーを構成します:**

  ```csharp Program.cs theme={null}
  builder.Services.AddAuthorization(options =>
  {
      options.AddPolicy("read:messages", policy =>
          policy.RequireClaim("scope", "read:messages"));
      
      options.AddPolicy("write:messages", policy =>
          policy.RequireClaim("scope", "write:messages"));
  });
  ```

  **3. エンドポイントにポリシーを適用します:**

  ```csharp theme={null}
  app.MapGet("/api/messages", () => 
      Results.Ok(new { Messages = new[] { "Message 1", "Message 2" } }))
      .RequireAuthorization("read:messages");

  app.MapPost("/api/messages", () => 
      Results.Created("/api/messages/1", new { Id = 1, Text = "New message" }))
      .RequireAuthorization("write:messages");
  ```

  アクセストークンをリクエストする際に、必要なスコープを含めます。

  ```bash theme={null}
  curl --request POST \
    --url https://YOUR_DOMAIN/oauth/token \
    --header 'content-type: application/json' \
    --data '{"client_id":"YOUR_CLIENT_ID","client_secret":"YOUR_CLIENT_SECRET","audience":"YOUR_AUDIENCE","grant_type":"client_credentials","scope":"read:messages write:messages"}'
  ```
</Accordion>

<Accordion title="強化されたセキュリティのための DPoP の活用">
  DPoP (Demonstration of Proof-of-Possession) は、アクセストークンを暗号鍵に束縛し、トークンの盗難やリプレイ攻撃を防ぎます。

  **DPoP サポートを有効化する:**

  ```csharp Program.cs theme={null}
  builder.Services.AddAuth0ApiAuthentication(options =>
  {
      options.Domain = builder.Configuration["Auth0:Domain"];
      options.JwtBearerOptions = new JwtBearerOptions
      {
          Audience = builder.Configuration["Auth0:Audience"]
      };
  }).WithDPoP();  // デフォルト設定で DPoP を有効化
  ```

  **DPoP モード:**

  DPoP と Bearer トークンの両方を受け入れる（デフォルト）:

  ```csharp theme={null}
  using Auth0.AspNetCore.Authentication.Api.DPoP;

  .WithDPoP(dpopOptions =>
  {
      dpopOptions.Mode = DPoPModes.Allowed;
  });
  ```

  DPoP トークンのみを受け入れ、Bearer トークンを拒否する:

  ```csharp theme={null}
  using Auth0.AspNetCore.Authentication.Api.DPoP;

  .WithDPoP(dpopOptions =>
  {
      dpopOptions.Mode = DPoPModes.Required;
  });
  ```

  時刻検証用パラメーターを構成する:

  ```csharp theme={null}
  .WithDPoP(dpopOptions =>
  {
      dpopOptions.Mode = DPoPModes.Allowed;
      dpopOptions.IatOffset = 300;  // 最大 5 分前までの DPoP 証明を許可
      dpopOptions.Leeway = 30;      // 30 秒のクロックスキュー許容範囲
  });
  ```

  <Info>
    DPoP の詳細については、[Auth0 DPoP ドキュメント](https://auth0.com/docs/secure/sender-constraining/demonstrating-proof-of-possession-dpop) を参照してください。
  </Info>
</Accordion>

<Accordion title="カスタム認可ポリシーの実装">
  複雑な要件に対応する再利用可能な認可ポリシーを作成できます。

  **1. カスタム要件を作成する:**

  ```csharp Authorization/HasScopeRequirement.cs theme={null}
  using Microsoft.AspNetCore.Authorization;

  namespace Auth0Api.Authorization;

  public class HasScopeRequirement : IAuthorizationRequirement
  {
      public string Scope { get; }
      public string Issuer { get; }

      public HasScopeRequirement(string scope, string issuer)
      {
          Scope = scope;
          Issuer = issuer;
      }
  }
  ```

  **2. ハンドラーを作成する:**

  ```csharp Authorization/HasScopeHandler.cs theme={null}
  using Microsoft.AspNetCore.Authorization;

  namespace Auth0Api.Authorization;

  public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
  {
      protected override Task HandleRequirementAsync(
          AuthorizationHandlerContext context,
          HasScopeRequirement requirement)
      {
          if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
          {
              return Task.CompletedTask;
          }

          var scopes = context.User
              .FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer)?
              .Value.Split(' ');

          if (scopes?.Any(s => s == requirement.Scope) == true)
          {
              context.Succeed(requirement);
          }

          return Task.CompletedTask;
      }
  }
  ```

  **3. ポリシーを登録して使用する:**

  ```csharp Program.cs theme={null}
  using Auth0Api.Authorization;

  var builder = WebApplication.CreateBuilder(args);

  var domain = $"https://{builder.Configuration["Auth0:Domain"]}";

  builder.Services.AddAuth0ApiAuthentication(options =>
  {
      options.Domain = builder.Configuration["Auth0:Domain"];
      options.JwtBearerOptions = new JwtBearerOptions
      {
          Audience = builder.Configuration["Auth0:Audience"]
      };
  });

  builder.Services.AddAuthorization(options =>
  {
      options.AddPolicy("read:messages", policy =>
          policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
  });

  builder.Services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

  var app = builder.Build();
  // ... 残りの構成
  ```
</Accordion>

<Accordion title="ユーザー情報の取得">
  認証済みトークンからユーザー情報を抽出します。

  ```csharp theme={null}
  app.MapGet("/api/user-info", (HttpContext context) =>
  {
      var userId = context.User.FindFirst("sub")?.Value;
      var email = context.User.FindFirst("email")?.Value;
      var name = context.User.FindFirst("name")?.Value;
      var scopes = context.User.FindAll("scope")
          .SelectMany(c => c.Value.Split(' '))
          .Distinct();

      return Results.Ok(new
      {
          UserId = userId,
          Email = email,
          Name = name,
          Scopes = scopes
      });
  })
  .RequireAuthorization();
  ```
</Accordion>

<Accordion title="カスタム トークン検証">
  特定の要件に合わせて JWT トークンの検証パラメーターをカスタマイズします。

  ```csharp Program.cs theme={null}
  using Microsoft.IdentityModel.Tokens;
  using System.Security.Claims;

  builder.Services.AddAuth0ApiAuthentication(options =>
  {
      options.Domain = builder.Configuration["Auth0:Domain"];
      options.JwtBearerOptions = new JwtBearerOptions
      {
          Audience = builder.Configuration["Auth0:Audience"],
          
          TokenValidationParameters = new TokenValidationParameters
          {
              ValidateIssuerSigningKey = true,
              ValidateIssuer = true,
              ValidateAudience = true,
              ValidateLifetime = true,
              ClockSkew = TimeSpan.FromMinutes(5),
              NameClaimType = ClaimTypes.NameIdentifier,
              RoleClaimType = "https://my-app.com/roles"
          },
          
          Events = new JwtBearerEvents
          {
              OnAuthenticationFailed = context =>
              {
                  Console.WriteLine($"Authentication failed: {context.Exception.Message}");
                  return Task.CompletedTask;
              },
              
              OnTokenValidated = context =>
              {
                  var userId = context.Principal?.FindFirst("sub")?.Value;
                  Console.WriteLine($"Token validated for user: {userId}");
                  return Task.CompletedTask;
              }
          }
      };
  });
  ```
</Accordion>

***

<div id="additional-resources">
  ## 追加リソース
</div>

<CardGroup cols={3}>
  <Card title="SDK ドキュメント" icon="book" href="https://github.com/auth0/aspnetcore-api">
    完全な SDK ドキュメントと API リファレンス
  </Card>

  <Card title="移行ガイド" icon="arrow-right-arrow-left" href="https://github.com/auth0/aspnetcore-api/blob/master/MIGRATION.md">
    JWT Bearer 認証から移行する
  </Card>

  <Card title="コード例" icon="code" href="https://github.com/auth0/aspnetcore-api/blob/master/EXAMPLES.md">
    充実したコード例とパターン
  </Card>

  <Card title="DPoP ドキュメント" icon="shield" href="https://auth0.com/docs/secure/sender-constraining/demonstrating-proof-of-possession-dpop">
    Proof-of-Possession によるセキュリティについて学ぶ
  </Card>

  <Card title="トークンのベストプラクティス" icon="key" href="https://auth0.com/docs/secure/tokens/token-best-practices">
    トークンのセキュリティに関するベストプラクティス
  </Card>

  <Card title="コミュニティフォーラム" icon="comments" href="https://community.auth0.com/">
    Auth0 コミュニティでサポートを受ける
  </Card>
</CardGroup>

***

<div id="common-issues">
  ## Common Issues
</div>

<AccordionGroup>
  <Accordion title="401 Unauthorized - 無効なオーディエンス">
    **問題:** オーディエンスの不一致エラーにより、トークン検証に失敗します。

    **解決方法:** `appsettings.json` の `Audience` が Auth0 API の Identifier と完全に一致していることを確認します。トークン内の audience クレームはこの値と一致している必要があります。

    ```json theme={null}
    {
      "Auth0": {
        "Audience": "https://my-api"  // Auth0 API Identifier と一致している必要があります
      }
    }
    ```
  </Accordion>

  <Accordion title="401 Unauthorized - 無効な issuer">
    **問題:** issuer エラーにより、トークン検証に失敗します。

    **解決方法:** ドメインが正しく設定されており、`https://` を含んでいないことを確認します。ライブラリは自動的に `https://{Domain}` という形式で authority を構築します。

    ```json theme={null}
    {
      "Auth0": {
        "Domain": "your-tenant.auth0.com"  // https:// は不要です
      }
    }
    ```
  </Accordion>

  <Accordion title="設定値が見つからない">
    **問題:** `ArgumentNullException: Value cannot be null. (Parameter 'Domain')` などのエラーが発生します。

    **解決方法:** `appsettings.json` に Auth0 セクションがあり、その中に Domain と Audience の値が含まれていることを確認します。設定が正しく読み込まれているかを確認します:

    ```csharp theme={null}
    builder.Services.AddAuth0ApiAuthentication(options =>
    {
        options.Domain = builder.Configuration["Auth0:Domain"]
            ?? throw new InvalidOperationException("Auth0:Domain is required");
        options.JwtBearerOptions = new JwtBearerOptions
        {
            Audience = builder.Configuration["Auth0:Audience"]
                ?? throw new InvalidOperationException("Auth0:Audience is required")
        };
    });
    ```
  </Accordion>

  <Accordion title="開発環境での HTTPS 証明書エラー">
    **問題:** ローカルで実行した際に SSL/TLS 証明書エラーが発生します。

    **解決方法:** 開発用証明書を信頼済みに設定します:

    ```bash theme={null}
    dotnet dev-certs https --trust
    ```

    または、新しい証明書を生成します:

    ```bash theme={null}
    dotnet dev-certs https --clean
    dotnet dev-certs https --trust
    ```
  </Accordion>

  <Accordion title="ミドルウェアの順序の問題">
    **問題:** 設定が正しいにもかかわらず、認証が機能しません。

    **解決方法:** ミドルウェアの順序が正しいことを確認します。`UseAuthentication()` は `UseAuthorization()` の前に記述する必要があります:

    ```csharp theme={null}
    app.UseAuthentication();  // UseAuthorization の前である必要があります
    app.UseAuthorization();
    app.MapControllers();
    ```
  </Accordion>

  <Accordion title="認可ポリシーでスコープが機能しない">
    **問題:** スコープベースの認可ポリシーが常に失敗します。

    **解決方法:** アクセストークンに必要なスコープが含まれていることを確認します。トークンをリクエストする際に、スコープを指定します:

    ```bash theme={null}
    curl --request POST \
      --url https://YOUR_DOMAIN/oauth/token \
      --data '{"client_id":"...","client_secret":"...","audience":"...","grant_type":"client_credentials","scope":"read:messages write:messages"}'
    ```

    また、Auth0 の API 設定でスコープが定義されていることを確認します（Dashboard → APIs → 対象の API → Permissions）。
  </Accordion>
</AccordionGroup>

***

<div id="sample-application">
  ## サンプルアプリケーション
</div>

すべての機能を網羅した完全なサンプルアプリケーションは、ソフトウェア開発キット (SDK) のリポジトリで入手できます。

<Card title="Playground アプリケーション" icon="github" href="https://github.com/auth0/aspnetcore-api/tree/master/Auth0.AspNetCore.Authentication.Api.Playground">
  公開エンドポイントおよび保護されたエンドポイント、DPoP 対応、Swagger UI との統合、Postman コレクションを含みます
</Card>

クローンして実行します:

```bash theme={null}
git clone https://github.com/auth0/aspnetcore-api.git
cd aspnetcore-api/Auth0.AspNetCore.Authentication.Api.Playground
# Auth0 の設定で appsettings.json を更新します
dotnet run
```
