メインコンテンツへスキップ
このクイックスタートは現在ベータ版です。ぜひフィードバックをお寄せください。

AI を使って Auth0 を統合する

Claude Code、Cursor、GitHub Copilot などの AI コーディングアシスタントを使用している場合は、agent skills を使って、数分で Auth0 認証を自動的に追加できます。インストール:
npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-aspnetcore-api
次に、AI アシスタントに次のように依頼します。
Add Auth0 JWT authentication to my ASP.NET Core Web API
AI アシスタントが、Auth0 API の作成、credentials の取得、Auth0 ASP.NET Core Authentication API SDK のインストール、JWT ベアラー認証の構成、保護された API エンドポイントの実装を自動的に行います。agent skills の詳細なドキュメント →
前提条件: 開始する前に、次のものがインストールされていることを確認してください。
  • .NET 8.0 SDK 以降
  • 使用する IDE (Visual Studio 2022、VS Code、または Rider)
.NET バージョンの互換性: このクイックスタートは .NET 8.0 以降で動作します。

はじめに

このクイックスタートでは、ASP.NET Core Web API に Auth0 JWT 認証を追加する方法を紹介します。Auth0 ASP.NET Core API SDK を使用して、保護されたエンドポイントを持つ安全な API を構築します。
1

新規プロジェクトを作成する

このクイックスタート向けの新しい ASP.NET Core Web API プロジェクトを作成する
dotnet new webapi -n Auth0Api
プロジェクトを開く
cd Auth0Api
2

Auth0 SDKをインストールする

dotnet add package Auth0.AspNetCore.Authentication.Api
3

Auth0 API をセットアップする

次に、Auth0テナントで新しいAPIを作成し、その設定をプロジェクトに追加します。CLIコマンドを実行して自動的に行う方法と、Dashboardから手動で行う方法のいずれかを選択できます。
Auth0 API を作成し、appsettings.json ファイルを更新するには、プロジェクトのルートディレクトリで次のコマンドを実行します。
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
4

認証を設定

Program.cs の内容をすべて、次のコードに置き換えます。
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.Run();
5

パブリックエンドポイントと保護されたエンドポイントを作成する

認証をテストするためのエンドポイントを追加します。Program.csapp.Run() の前に、次のコードを追加します。
Program.cs
// パブリックエンドポイント - 認証不要
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");
6

API を起動する

dotnet run
これで、API は https://localhost:7190 で実行中です (またはそれに類似した URL です。正確な URL はコンソールの出力を確認してください) 。
チェックポイントこれで、Auth0 で保護された完全に動作する API が localhost 上で実行されているはずです。

高度な使い方

アクセストークンを使用して、保護されたエンドポイントをテストします。1. アクセストークンを取得します。 Auth0 から Client Credentials Flow を使用して取得します。
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"}'
YOUR_CLIENT_IDYOUR_CLIENT_SECRET を取得するには、Auth0 Dashboard で Machine to Machine Application を作成し、API に対して認可します。
2. 公開エンドポイントをテストします。 (200 OK が返るはずです)
curl https://localhost:7190/api/public
3. 認証なしで保護されたエンドポイントをテストします。 (401 Unauthorized が返るはずです)
curl https://localhost:7190/api/private
4. トークンを使用して保護されたエンドポイントを呼び出します。
curl https://localhost:7190/api/private \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
より大規模な API では、最小 API エンドポイントではなくコントローラーを使用します。1. コントローラーのサポートを追加します。
Program.cs
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 を作成します。
Controllers/MessagesController.cs
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" } });
    }
}
アクセストークン内の特定のスコープに基づいてエンドポイントを保護します。1. Auth0 API でスコープを定義します。Auth0 Dashboard → APIs → Your API → Permissions で、スコープを追加します。
  • read:messages - メッセージの読み取り
  • write:messages - メッセージの書き込み
2. 認可ポリシーを設定します。
Program.cs
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. エンドポイントにポリシーを適用します。
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");
アクセストークンをリクエストする際は、必要なスコープを含めます。
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"}'
DPoP (Demonstration of Proof-of-Possession) は、アクセストークンを暗号鍵に関連付けることで、トークンの窃取やリプレイ攻撃を防止します。DPoP サポートを有効にする:
Program.cs
builder.Services.AddAuth0ApiAuthentication(options =>
{
    options.Domain = builder.Configuration["Auth0:Domain"];
    options.JwtBearerOptions = new JwtBearerOptions
    {
        Audience = builder.Configuration["Auth0:Audience"]
    };
}).WithDPoP();  // 既定の設定で DPoP を有効化
DPoP モード:DPoP トークンと Bearer トークンの両方を受け入れる (既定) :
using Auth0.AspNetCore.Authentication.Api.DPoP;

.WithDPoP(dpopOptions =>
{
    dpopOptions.Mode = DPoPModes.Allowed;
});
DPoP トークンのみを受け入れ、Bearer トークンは拒否する:
using Auth0.AspNetCore.Authentication.Api.DPoP;

.WithDPoP(dpopOptions =>
{
    dpopOptions.Mode = DPoPModes.Required;
});
時刻検証パラメーターを設定する:
.WithDPoP(dpopOptions =>
{
    dpopOptions.Mode = DPoPModes.Allowed;
    dpopOptions.IatOffset = 300;  // 5 分前までに生成された DPoP proof を許可
    dpopOptions.Leeway = 30;      // 30 秒の時刻ずれを許容
});
DPoP の詳細については、Auth0 の DPoP ドキュメントを参照してください。
複雑な要件に対応するため、再利用可能な認可ポリシーを作成します。1. カスタム要件を作成する:
Authorization/HasScopeRequirement.cs
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. ハンドラーを作成する:
Authorization/HasScopeHandler.cs
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. ポリシーを登録して使用する:
Program.cs
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();
// ... 残りの構成
認証済みトークンからユーザー情報を取得します。
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();
特定の要件に応じて、JWT の検証パラメーターをカスタマイズします。
Program.cs
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;
            }
        }
    };
});

参考資料

SDK ドキュメント

SDK の完全なドキュメントと API リファレンス

移行ガイド

JWT ベアラー認証からの移行

コード例

包括的なコード例とパターン

DPoP ドキュメント

所有証明によるセキュリティについて確認する

トークンのベストプラクティス

トークン セキュリティのベストプラクティス

コミュニティフォーラム

Auth0 コミュニティでサポートを受ける

よくある問題

問題: オーディエンスの不一致により、トークンの検証が失敗します。解決策: appsettings.jsonAudience が Auth0 API の Identifier と完全に一致していることを確認してください。トークン内の audience クレームもこの値と一致している必要があります。
{
  "Auth0": {
    "Audience": "https://my-api"  // Auth0 API Identifier と一致している必要があります
  }
}
問題: issuer エラーにより、トークンの検証が失敗します。解決策: ドメインが正しく、https:// が含まれていないことを確認してください。ライブラリは https://{Domain} の形式で authority を自動的に構築します。
{
  "Auth0": {
    "Domain": "your-tenant.auth0.com"  // https:// は不要
  }
}
問題: ArgumentNullException: Value cannot be null. (Parameter 'Domain') などのエラーが発生します。解決策: appsettings.json に Domain と Audience の値を含む Auth0 セクションがあることを確認してください。あわせて、設定が正しく読み込まれていることも確認してください。
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")
    };
});
問題: ローカル実行時に SSL/TLS 証明書エラーが発生します。解決策: 開発用証明書を信頼してください。
dotnet dev-certs https --trust
または、新しい証明書を生成してください。
dotnet dev-certs https --clean
dotnet dev-certs https --trust
問題: 設定が正しいにもかかわらず、認証が機能しません。解決策: ミドルウェアが正しい順序で配置されていることを確認してください。UseAuthentication()UseAuthorization() より前に指定する必要があります。
app.UseAuthentication();  // UseAuthorization より前である必要があります
app.UseAuthorization();
app.MapControllers();
問題: スコープベースの認可ポリシーが常に失敗します。解決策: アクセストークンに必要なスコープが含まれていることを確認してください。トークンをリクエストする際は、スコープを指定してください。
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 → Your API → Permissions) 。

サンプルアプリケーション

すべての機能を網羅した完全なサンプルアプリケーションを、SDK リポジトリで利用できます。

プレイグラウンドアプリケーション

パブリックエンドポイントと保護されたエンドポイント、DPoP サポート、Swagger UI との統合、Postman コレクションが含まれています
クローンして実行します:
git clone https://github.com/auth0/aspnetcore-api.git
cd aspnetcore-api/Auth0.AspNetCore.Authentication.Api.Playground
# appsettings.jsonをAuth0の設定で更新する
dotnet run