Microsoft.Identity.Web とダウンストリーム API の統合

Microsoft。Identity.Web には、ASP.NET Core、OWIN、または.NET アプリケーションからダウンストリーム API (Microsoft Graph、Azure サービス、カスタム REST API など) を呼び出すための複数の方法が用意されています。 この記事は、シナリオに適したアプローチを選択し、すぐに開始するのに役立ちます。

アプローチの選択

このデシジョン ツリーを使用して、シナリオに最適な方法を選択します。

API の種類/シナリオ 決定/条件 推奨されるクライアント/クラス
Microsoft Graph Microsoft Graph API を呼び出す必要がある GraphServiceClient
Azure SDK (ストレージ、KeyVault など) Azure API を呼び出す必要があります (Azure SDK) Azure SDK クライアントでの MicrosoftIdentityTokenCredential
トークン バインディングを使用したカスタム API 証明書バインドによるセキュリティの強化 (mTLS PoP) IDownstreamApi と ProtocolScheme: "MTLS_POP"
トークン バインディングを使用したカスタム API HttpClient 統合によるセキュリティの強化 (mTLS PoP) MicrosoftIdentityMessageHandler ProtocolScheme: "MTLS_POP"
カスタム API シンプルで構成可能 IDownstreamApi
カスタム API HttpClient + デリゲーティングハンドラーの使用 MicrosoftIdentityMessageHandler
カスタム API HttpClient の使用 IAuthorizationHeaderProvider

複雑さと柔軟性によるアプローチの比較

次の表は、それぞれのアプローチを、目的のユース ケース、複雑さレベル、および柔軟性によってまとめたものです。

方法 最適な対象者 複雑さ コンフィギュレーション 柔軟性
GraphServiceClient Microsoft Graph API 簡単 中程度
MicrosoftIdentityTokenCredential Azure SDK クライアント 簡単
IDownstreamApi 標準パターンを使用する REST API JSON + コード 中程度
MicrosoftIdentityMessageHandler 認証パイプラインを使用した HttpClient 中程度 Code
IAuthorizationHeaderProvider カスタム認証ロジック Code 非常に高

トークン取得パターン

Microsoft。Identity.Web では、次の 3 つの主要なトークン取得パターンがサポートされています。

graph LR
    A[Token Acquisition] --> B[Delegated<br/>On behalf of user]
    A --> C[App-Only<br/>Application permissions in all apps]
    A --> D[On-Behalf-Of OBO<br/>in web API]

    B --> B1[Web Apps]
    B --> B2[Daemon acting as user / user agent]
    C --> C1[Daemon Apps]
    C --> C2[Web APIs with app permissions]
    D --> D1[Web APIs calling other APIs]

    style B fill:#cfe2ff
    style C fill:#fff3cd
    style D fill:#f8d7da

委任されたアクセス許可 (ユーザー トークン)

サインインしているユーザーの代わりにアプリケーションが動作する場合は、委任されたアクセス許可を使用します。

  • シナリオ: Web アプリは、サインインしているユーザーと自律エージェントのユーザー ID に代わって API を呼び出します。
  • トークンの種類: 委任されたアクセス許可を持つアクセス トークン
  • メソッド: CreateAuthorizationHeaderForUserAsync()GetForUserAsync()

アプリケーションのアクセス許可 (アプリ専用トークン)

ユーザーが存在せず、アプリがそれ自体として認証される場合は、アプリケーションのアクセス許可を使用します。

  • シナリオ: デーモン アプリまたはバックグラウンド サービスが API を呼び出す。 自律エージェントアイデンティティ
  • トークンの種類: アプリケーションのアクセス許可を持つアクセス トークン
  • メソッド: CreateAuthorizationHeaderForAppAsync()GetForAppAsync()

OBO (代理) フロー

Web API がユーザーの ID を維持しながら別のダウンストリーム API を呼び出す必要がある場合は、OBO フローを使用します。

  • シナリオ: Web API はユーザー トークンを受け取り、そのユーザーおよび対話型エージェントに代わって別の API を呼び出します。
  • トークンの種類: OBO フローを使用した新しいアクセス トークン
  • メソッド: CreateAuthorizationHeaderForUserAsync() Web API のコンテキストから

トークン バインディング (mTLS PoP)

トークン バインディングでは、アクセス トークンを X.509 証明書に暗号化して結び付けることで、セキュリティの追加レイヤーが追加されます。

  • シナリオ: RFC 8705 に従ってトークンが証明書に暗号化的にバインドされるセキュリティ強化
  • トークンの種類: 証明書バインドを使用したアクセス トークン (cnf 要求)
  • メソッド:
  • セキュリティ: トークンを特定の証明書にバインドすることでトークンの盗難を防ぐ

mTLS PoP を使用したトークン バインドの詳細

クイック スタート コードの例

次の例では、アプリケーションに適応できるエンドツーエンドのコードを使用した各アプローチを示します。

次の例では、GraphServiceClientを登録し、それを使用して、サインインしているユーザーの代わりに、およびアプリ専用の呼び出しとしてMicrosoft Graphを呼び出します。

// Installation
// dotnet add package Microsoft.Identity.Web.GraphServiceClient

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddMicrosoftGraph();

// Usage in controller
public class HomeController : Controller
{
    private readonly GraphServiceClient _graphClient;

    public HomeController(GraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<IActionResult> Profile()
    {
        // Delegated - calls on behalf of signed-in user
        var user = await _graphClient.Me.GetAsync();

        // App-only - requires app permissions
        var users = await _graphClient.Users
            .GetAsync(r => r.Options.WithAppOnly());

        return View(user);
    }
}

Microsoft Graph統合の詳細については

GraphServiceClient の移行と詳細な使用方法

次の例では、MicrosoftIdentityTokenCredential を登録し、Azure Blob Storage クライアントに渡します。

// Installation
// dotnet add package Microsoft.Identity.Web.Azure
// dotnet add package Azure.Storage.Blobs

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddMicrosoftIdentityAzureTokenCredential();

// Usage
public class StorageService
{
    private readonly MicrosoftIdentityTokenCredential _credential;

    public StorageService(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
    }

    public async Task<List<string>> ListBlobsAsync()
    {
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);

        var container = blobClient.GetBlobContainerClient("mycontainer");
        var blobs = new List<string>();

        await foreach (var blob in container.GetBlobsAsync())
        {
            blobs.Add(blob.Name);
        }

        return blobs;
    }
}

Azure SDK統合の詳細についてはを参照してください>

次の例では、 appsettings.json で名前付きダウンストリーム API を構成し、委任されたトークンとアプリ専用トークンの両方で呼び出します。

// Installation
// dotnet add package Microsoft.Identity.Web.DownstreamApi

// appsettings.json
{
  "DownstreamApis": {
    "MyApi": {
      "BaseUrl": "https://myapi.example.com",
      "Scopes": ["api://myapi/read", "api://myapi/write"]
    }
  }
}

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddDownstreamApis(
    builder.Configuration.GetSection("DownstreamApis"));

// Usage
public class ApiService
{
    private readonly IDownstreamApi _api;

    public ApiService(IDownstreamApi api)
    {
        _api = api;
    }

    public async Task<Product> GetProductAsync(int id)
    {
        // Delegated - on behalf of user
        return await _api.GetForUserAsync<Product>(
            "MyApi",
            $"api/products/{id}"
        );
    }

    public async Task<List<Product>> GetAllProductsAsync()
    {
        // App-only - using app permissions
        return await _api.GetForAppAsync<List<Product>>(
            "MyApi",
            "api/products");
    }
}

IDownstreamApi の詳細

mTLS PoP を使用したトークン バインド (セキュリティ強化)

トークン バインドでは、アクセス トークンを X.509 証明書に暗号化的にバインドすることで、セキュリティが強化されます。 トークンがインターセプトされた場合でも、対応する証明書がないと使用できません。

// Installation
// dotnet add package Microsoft.Identity.Web.DownstreamApi

// appsettings.json
{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "StoreWithDistinguishedName",
        "CertificateStorePath": "CurrentUser/My",
        "CertificateDistinguishedName": "CN=YourCertificate"
      }
    ],
    "SendX5c": true
  },
  "SecureApi": {
    "BaseUrl": "https://api.contoso.com/",
    "RelativePath": "api/data",
    "ProtocolScheme": "MTLS_POP",
    "RequestAppToken": true,
    "Scopes": [ "api://your-api/.default" ]
  }
}

// Startup configuration
builder.Services.AddDownstreamApi(
    "SecureApi",
    builder.Configuration.GetSection("SecureApi"));

// Usage
public class SecureApiService
{
    private readonly IDownstreamApi _api;

    public SecureApiService(IDownstreamApi api)
    {
        _api = api;
    }

    public async Task<SecureData> GetSecureDataAsync()
    {
        // Token is bound to certificate - enhanced security
        return await _api.GetForAppAsync<SecureData>("SecureApi");
    }
}

主な利点:

  • トークン盗難防止: 盗まれたトークンは証明書なしでは役に立ちません
  • リプレイ攻撃防止: 異なるクライアントからトークンを再生することはできません
  • ゼロ トラストアラインメント: クライアントとトークンの間の強力な暗号化バインディング

トークン バインディング (mTLS PoP) の詳細を確認する

MicrosoftIdentityMessageHandler (HttpClient 統合用)

次の例では、すべての送信要求に承認ヘッダーが自動的に含まれるように、委任ハンドラーを HttpClient に追加します。 ハンドラーは起動時にスコープを登録し、個々の要求でトークン オプションをオーバーライドできます。

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddHttpClient("MyApiClient", client =>
{
    client.BaseAddress = new Uri("https://myapi.example.com");
})
.AddHttpMessageHandler(sp => new MicrosoftIdentityMessageHandler(
    sp.GetRequiredService<IAuthorizationHeaderProvider>(),
    new MicrosoftIdentityMessageHandlerOptions
    {
        Scopes = new[] { "api://myapi/.default" }
    }));

// Usage
public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("MyApiClient");
    }

    public async Task<Product> GetProductAsync(int id)
    {
        var request = new HttpRequestMessage(HttpMethod.Get, $"api/products/{id}")
            .WithAuthenticationOptions(options =>
            {
                options.RequestAppToken = false; // Use delegated token
                options.scopes = [ "myApi.scopes" ];
            });

        var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<Product>();
    }
}

MicrosoftIdentityMessageHandler の詳細を確認する

IAuthorizationHeaderProvider (最大の柔軟性)

次の例では、カスタム ヘッダーと共に任意の HTTP 要求にアタッチできるように、承認ヘッダーを直接取得します。

// Direct usage for custom scenarios
public class CustomAuthService
{
    private readonly IAuthorizationHeaderProvider _headerProvider;

    public CustomAuthService(IAuthorizationHeaderProvider headerProvider)
    {
        _headerProvider = headerProvider;
    }

    public async Task<string> CallApiAsync()
    {
        // Get auth header (includes "Bearer " + token)
        string authHeader = await _headerProvider
            .CreateAuthorizationHeaderForUserAsync(
                scopes: new[] { "api://myapi/.default" });

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("Authorization", authHeader);
        client.DefaultRequestHeaders.Add("X-Custom-Header", "MyValue");

        var response = await client.GetStringAsync("https://myapi.example.com/data");
        return response;
    }
}

IAuthorizationHeaderProvider の詳細を確認する

構成パターン

Microsoft。Identity.Web では、JSON 構成とコードベースの構成の両方がサポートされています。

appsettings.json 構成

次の JSON は、Microsoft Entra ID資格情報と 2 つのダウンストリーム API を登録する一般的な構成を示しています。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity"
      }
    ]
  },
  "DownstreamApis": {
    "MicrosoftGraph": {
      "BaseUrl": "https://graph.microsoft.com/v1.0",
      "Scopes": ["User.Read", "Mail.Read"]
    },
    "MyApi": {
      "BaseUrl": "https://myapi.example.com",
      "Scopes": ["api://myapi/read"]
    }
  }
}

Note

デーモン/コンソール アプリの場合は、 appsettings.json プロパティを設定します。 "出力ディレクトリにコピーする" = "新しい場合はコピー"

資格情報の構成の詳細

コードベースの構成

次の例に示すように、資格情報とダウンストリーム API 全体をコードで構成することもできます。

// Explicit configuration in code
builder.Services.Configure<MicrosoftIdentityApplicationOptions>(options =>
{
    options.Instance = "https://login.microsoftonline.com/";
    options.TenantId = "your-tenant-id";
    options.ClientId = "your-client-id";
    options.ClientCredentials = new[]
    {
        CertificateDescription.FromKeyVault(
            "https://myvault.vault.azure.net",
            "MyCertificate")
    };
});

builder.Services.AddDownstreamApi("MyApi", options =>
{
    options.BaseUrl = "https://myapi.example.com";
    options.Scopes = new[] { "api://myapi/read" };
});

シナリオ固有のガイド

最適な方法は、API の呼び出し元によって異なります。

Web アプリの統合

Web アプリは通常、サインインしているユーザーの代わりにダウンストリーム API を呼び出します。

  • プライマリ パターン: 委任されたアクセス許可 (ユーザーに代わって)
  • トークンの取得: サインイン中に自動的に発生します
  • 特別な考慮事項: 増分同意、同意エラーの処理

Web Apps ガイド

Web API の統合

Web API は、On-Behalf-Of フローを利用して、受信したユーザートークンをダウンストリーム API 用の新しいトークンと交換します。

  • プライマリ パターン: オンビハーフオブ (OBO) フロー
  • トークン取得: 受信したトークンをダウンストリームトークンへ交換します。
  • 特別な考慮事項: 実行時間の長いプロセス、トークン キャッシュ、エージェント ID。

Web API ガイドを読む

デーモン アプリの統合

デーモン アプリは、サインインしているユーザーなしで自身として認証されます。

  • プライマリ パターン: アプリケーションのアクセス許可 (アプリのみ)
  • トークンの取得: クライアント資格情報フロー
  • 特別な考慮事項: ユーザー コンテキストがなく、管理者の同意が必要
  • 高度: 自律エージェント、エージェント ユーザー識別子

デーモン アプリケーション ガイドを読む

トークン取得のエラー処理

すべてのトークン取得メソッドは、アプリケーションで処理する必要がある例外をスローできます。 Web アプリでは、 [AuthorizeForScope(scopes)] 属性がユーザーの増分同意または再署名を処理します。

次の例は、一般的なトークン取得例外をキャッチして処理する方法を示しています。

using Microsoft.Identity.Abstractions;

try
{
    var result = await _api.GetForUserAsync<Data>("MyApi", "api/data");
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
    // User needs to sign in or consent to additional scopes
    // In web apps, this triggers a redirect to Microsoft Entra ID
    throw;
}
catch (HttpRequestException ex)
{
    // Downstream API returned error
    _logger.LogError(ex, "API call failed");
}

一般的なエラー シナリオ

次の表に、最も一般的な例外とその解決方法を示します。

例外 説明 ソリューション
MicrosoftIdentityWebChallengeUserException ユーザーの同意が必要 同意のためにMicrosoft Entra IDにリダイレクトします。 AuthorizeForScopes 属性または ConsentHandler クラスを使用する
MsalUiRequiredException 対話型認証が必要 チャレンジを含むWebアプリで処理を行う
MsalServiceException Microsoft Entra ID サービス エラー 構成を確認し、再試行する
HttpRequestException ダウンストリーム API エラー API 固有のエラーを処理する

必要な NuGet パッケージ

シナリオに一致するパッケージを選択します。 次の表に、各パッケージとその使用方法を示します。

パッケージ Purpose いつ使用するか
Microsoft.Identity.Web.TokenAcquisition トークン取得サービス コア パッケージ
Microsoft.Identity.Web.DownstreamApi IDownstreamApi の抽象化 REST API の呼び出し
Microsoft.Identity.Web.GraphServiceClient Microsoft Graph統合 Microsoft Graphの呼び出し (migration guide)
Microsoft。Identity.Web。Azure Azure SDK統合 Azure サービスの呼び出し
Microsoft。Identity.Web ASP.NET Core Web アプリと Web API ASP.NET Core
Microsoft。Identity.Web.OWIN ASP.NET OWIN Web アプリと Web API OWIN

詳細なチュートリアルと高度なシナリオについては、これらのガイドを参照してください。