MicrosoftIdentityTokenCredential でAzure SDKを呼び出す

Microsoft.Identity.WebのMicrosoftIdentityTokenCredentialを使用して、Microsoft Entra IDでAzure SDKクライアント(ストレージ、Key Vault、Service Busなど)を認証します。

MicrosoftIdentityTokenCredential について

MicrosoftIdentityTokenCredential クラスは、Azure SDK TokenCredential インターフェイスを実装します。 この統合により、アプリケーション全体で同じ認証構成とトークン キャッシュ インフラストラクチャを使用できます。

特典を確認する

MicrosoftIdentityTokenCredential には、次の利点があります。

  • Unified Authentication: Web アプリ、API、Azure サービスに対して同じ認証構成を使用します
  • トークン キャッシュ: トークンの自動キャッシュと更新
  • 委任されたアプリのアクセス許可: ユーザー トークンとアプリケーション トークンの両方のサポート
  • エージェント ID: エージェント ID 機能と互換性がある
  • 管理 ID: Azure マネージド ID とのシームレスな統合

パッケージのインストール

Azure統合パッケージをインストールします。

dotnet add package Microsoft.Identity.Web.Azure

次に、必要なAzure SDKクライアント パッケージをインストールします。

# Examples
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Security.KeyVault.Secrets
dotnet add package Azure.Messaging.ServiceBus
dotnet add package Azure.Data.Tables

ASP.NET Coreを設定する

1. サービスを構成する

次のコードは、認証を登録し、Azureトークン資格情報のサポートをアプリケーションに追加します。

using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

// Add authentication
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

// Add Azure token credential support
builder.Services.AddMicrosoftIdentityAzureTokenCredential();

builder.Services.AddControllersWithViews();

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

2. appsettings.json を構成する

Microsoft Entra構成を appsettings.json ファイルに追加します。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity"
      }
    ]
  }
}

MicrosoftIdentityTokenCredential を使用する

Azure SDK クライアントを導入して使用する

次の例では、MicrosoftIdentityTokenCredential を挿入し、Azure Blob Storageと共に使用する方法を示します。 すべてのAzure SDK クライアントにも同じ方法が適用されます。

using Azure.Storage.Blobs;
using Microsoft.Identity.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[Authorize]
public class StorageController : Controller
{
    private readonly MicrosoftIdentityTokenCredential _credential;
    private readonly IConfiguration _configuration;
    
    public StorageController(
        MicrosoftIdentityTokenCredential credential,
        IConfiguration configuration)
    {
        _credential = credential;
        _configuration = configuration;
    }
    
    public async Task<IActionResult> ListBlobs()
    {
        // Create Azure SDK client with credential
        var blobClient = new BlobServiceClient(
            new Uri($"https://{_configuration["StorageAccountName"]}.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 View(blobs);
    }
}

委任されたアクセス許可を使用する

委任されたアクセス許可を使用して、サインインしているユーザーに代わってAzure サービスを呼び出します。

Azure Storageを使用してファイルをアップロードする

次のコントローラーは、委任されたトークンを使用してファイルをAzure Blob Storageにアップロードする方法を示しています。

using Azure.Storage.Blobs;
using Microsoft.Identity.Web;

[Authorize]
public class FileController : Controller
{
    private readonly MicrosoftIdentityTokenCredential _credential;
    
    public FileController(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
    }
    
    public async Task<IActionResult> UploadFile(IFormFile file)
    {
        // Credential will automatically acquire delegated token
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);
        
        var container = blobClient.GetBlobContainerClient("uploads");
        await container.CreateIfNotExistsAsync();
        
        var blob = container.GetBlobClient(file.FileName);
        await blob.UploadAsync(file.OpenReadStream(), overwrite: true);
        
        return Ok($"File {file.FileName} uploaded");
    }
}

アプリケーションのアクセス許可を使用する

ユーザー コンテキストが使用できない場合は、アプリケーションのアクセス許可で Azure サービスを呼び出します。

アプリ専用トークンを構成する

RequestAppTokenを資格情報オプションのtrueに設定して、アプリ専用トークンを取得します。

public class AzureService
{
    private readonly MicrosoftIdentityTokenCredential _credential;
    
    public AzureService(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
    }
    
    public async Task<List<string>> ListBlobsAsync()
    {
        // Configure credential for app-only token
        _credential.Options.RequestAppToken = true;
        
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);
        
        var container = blobClient.GetBlobContainerClient("data");
        var blobs = new List<string>();
        
        await foreach (var blob in container.GetBlobsAsync())
        {
            blobs.Add(blob.Name);
        }
        
        return blobs;
    }
}

デーモン アプリケーションを作成する

次の例は、アプリ専用のアクセス許可を持つAzure Blob Storageにアクセスするスタンドアロン デーモン アプリケーションを構築する方法を示しています。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
using Azure.Storage.Blobs;

class Program
{
    static async Task Main(string[] args)
    {
        // Build service provider
        var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
        tokenAcquirerFactory.Services.AddMicrosoftIdentityAzureTokenCredential();
        var sp = tokenAcquirerFactory.Build();
        
        // Get credential
        var credential = sp.GetRequiredService<MicrosoftIdentityTokenCredential>();
        credential.Options.RequestAppToken = true;
        
        // Use with Azure SDK
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            credential);
        
        var container = blobClient.GetBlobContainerClient("data");
        
        await foreach (var blob in container.GetBlobsAsync())
        {
            Console.WriteLine($"Blob: {blob.Name}");
        }
    }
}

エージェント ID を統合する

MicrosoftIdentityTokenCredential は、 Options プロパティを使用してエージェント ID をサポートします。 次のサービス クラスは、エージェント ID とエージェント ユーザー ID を構成する方法を示しています。

using Microsoft.Identity.Web;

public class AgentService
{
    private readonly MicrosoftIdentityTokenCredential _credential;
    
    public AgentService(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
    }
    
    public async Task<List<string>> ListBlobsForAgentAsync(string agentIdentity)
    {
        // Configure for agent identity
        _credential.Options.WithAgentIdentity(agentIdentity);
        _credential.Options.RequestAppToken = true;
        
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);
        
        var container = blobClient.GetBlobContainerClient("agent-data");
        var blobs = new List<string>();
        
        await foreach (var blob in container.GetBlobsAsync())
        {
            blobs.Add(blob.Name);
        }
        
        return blobs;
    }
    
    public async Task<string> GetSecretForAgentUserAsync(string agentIdentity, Guid userOid, string secretName)
    {
        // Configure for agent user identity
        _credential.Options.WithAgentUserIdentity(agentIdentity, userOid);
        
        var secretClient = new SecretClient(
            new Uri("https://myvault.vault.azure.net"),
            _credential);
        
        var secret = await secretClient.GetSecretAsync(secretName);
        return secret.Value.Value;
    }
}

詳細については 、エージェント ID のドキュメント を参照してください。

FIC とマネージド ID の構成

MicrosoftIdentityTokenCredential は、FIC とAzureマネージド ID で動作します。

マネージド ID 資格情報の構成

資格情報ソースとしてマネージド ID を使用するには、次の構成を追加します。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity"
      }
    ]
  }
}

システム割り当てマネージド ID を使用する

Azureにデプロイする際、資格情報はシステム割り当てマネージドIDを自動的に使用します。 次のサービス クラスは、このパターンを示しています。

// No additional code needed!
// When deployed to Azure, the credential automatically uses managed identity

public class StorageService
{
    private readonly MicrosoftIdentityTokenCredential _credential;
    
    public StorageService(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
        _credential.Options.RequestAppToken = true;
    }
    
    public async Task<List<string>> ListContainersAsync()
    {
        // Uses managed identity when running in Azure
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);
        
        var containers = new List<string>();
        await foreach (var container in blobClient.GetBlobContainersAsync())
        {
            containers.Add(container.Name);
        }
        
        return containers;
    }
}

ユーザー割り当てマネージド ID を使用する

ユーザー割り当てマネージド ID を使用する構成の ManagedIdentityClientId を指定します。

{
  "AzureAd": {
    "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity",
        "ManagedIdentityClientId": "user-assigned-identity-client-id"
      }
    ]
  }
}

OWIN 認証を実装する

OWIN を使用 ASP.NET アプリケーションの場合は、Azure トークン資格情報をスタートアップ クラスに登録します。

using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Owin;

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
     app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
     app.UseCookieAuthentication(new CookieAuthenticationOptions());

     OwinTokenAcquirerFactory factory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();

     app.AddMicrosoftIdentityWebApp(factory);
     factory.Services
        .AddMicrosoftIdentityAzureTokenCredential();
      factory.Build();
    }
}

ベスト プラクティスに従う

1. Azure SDK クライアントを再利用する

Azure SDKクライアントはスレッド セーフであるため、要求間で再利用します。 ただし、 MicrosoftIdentityTokenCredential はスコープ付きサービスであるため、シングルトンを作成する AddAzureServices()では使用できません。

2. 運用環境でマネージド ID を使用する

運用環境では、マネージド ID を使用した証明書なしの認証を優先します。

//  Good: Certificateless auth with managed identity
{
  "ClientCredentials": [
    {
      "SourceType": "SignedAssertionFromManagedIdentity"
    }
  ]
}

3. Azure SDK例外を処理する

Azure SDK呼び出しを try-catch ブロックでラップして、一般的な障害シナリオを処理します。

using Azure;

try
{
    var blob = await blobClient.DownloadAsync();
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
    // Blob not found
}
catch (RequestFailedException ex) when (ex.Status == 403)
{
    // Insufficient permissions
}
catch (RequestFailedException ex)
{
    _logger.LogError(ex, "Azure SDK call failed with status {Status}", ex.Status);
}

5. URI の構成を使用する

Azureリソース URI をハードコーディングするのではなく、構成に格納します。

//  Bad: Hardcoded URIs
var blobClient = new BlobServiceClient(new Uri("https://myaccount.blob.core.windows.net"), credential);

//  Good: Configuration-driven
var storageUri = _configuration["Azure:Storage:Uri"];
var blobClient = new BlobServiceClient(new Uri(storageUri), credential);

一般的なエラーのトラブルシューティング

"ManagedIdentityCredential 認証に失敗しました" を解決する

原因: マネージド ID が有効になっていないか、正しく構成されていません。

解決策:

  • Azure リソース (App Service、VM など) でマネージド ID を有効にする
  • ユーザー割り当て ID の場合は、ManagedIdentityClientId を指定します。
  • ID に必要な役割が割り当てられていることを確認する

"この要求は、この操作を実行する権限がありません" を解決します。

原因: Azure RBAC ロールの割り当てがない。

解決策:

  • マネージド ID またはユーザーに適切なロールを割り当てる
  • 例: BLOB 操作の "ストレージ BLOB データ共同作成者"
  • ロールの割り当てが反映されるまで最大 5 分待ちます

ローカル トークンの取得エラーを修正する

Cause: マネージド ID はAzureでのみ機能します。

解決策: 別の資格情報ソースをローカルで使用します。

{
  "ClientCredentials": [
    {
      "SourceType": "ClientSecret",
      "ClientSecret": "secret-for-local-dev"
    }
  ]
}

Azure リソースでスコープ エラーを修正する

原因: スコープの形式が正しくありません。

Solution: リソース固有のスコープAzure使用します。

  • ストレージ: https://storage.azure.com/user_impersonation または .default
  • KeyVault: https://vault.azure.net/user_impersonation または .default
  • Service Bus: https://servicebus.azure.net/user_impersonation または .default

次の手順: IDownstreamApi と IAuthorizationHeaderProvider を使用した カスタム API の呼び出 しについて説明します。