この記事では、Microsoftを使用してデーモン アプリケーション、バックグラウンド サービス、自律エージェントを構築します。Identity.Web。 これらのアプリケーションは、ユーザーの操作なしで実行され、 アプリケーション ID (クライアント資格情報) または エージェント ID を使用して認証されます。
サポートされているシナリオを理解する
Microsoft。Identity.Web では、次の 3 種類の非対話型アプリケーションがサポートされています。
| シナリオ | 認証の種類 | トークンの種類 | ユースケース(事例) |
|---|---|---|---|
| Standard デーモン | クライアント資格情報 (シークレット/証明書) | アプリ専用アクセス トークン | バックグラウンド サービス、スケジュールされたジョブ、データ処理 |
| 自律エージェント | クライアント資格情報を使用するエージェント識別 | エージェントのアプリ専用アクセス トークン | Copilotエージェント、自律的にエージェントIDを代理して動作するサービス。 (通常、保護された Web API の場合) |
| エージェント ユーザー ID | エージェント ユーザー ID | クライアント資格情報を持つエージェント ユーザー ID | エージェント ユーザー ID に代わって動作する自律サービス。 (通常、保護された Web API の場合) |
概要
前提条件
開始する前に、以下の項目があることを確認します:
- .NET 8.0 以降
- Microsoft Entra で、クライアント資格情報(クライアントシークレットまたは証明書)を使用してアプリを登録する
- エージェント シナリオの場合: Microsoft Entra テナントで設定されたエージェントの識別情報
パッケージをインストールする
必要な NuGet パッケージをプロジェクトに追加します。
dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Extensions.Hosting
構成方法を選択する
Microsoft。Identity.Web には、デーモン アプリケーションを構成する 2 つの方法があります。
オプション 1: TokenAcquirerFactory (単純なシナリオに推奨)
次の場合に最適です。 クイック プロトタイプ、コンソール アプリ、テスト、単純なデーモン サービス。
次のコードでは、TokenAcquirerFactoryを作成し、ダウンストリーム API とMicrosoft Graphを構成し、Graph APIを呼び出します。
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
// Get the token acquirer factory instance
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
// Configure downstream API and Microsoft Graph (optional)
tokenAcquirerFactory.Services.AddDownstreamApis(
tokenAcquirerFactory.Configuration.GetSection("DownstreamApis"))
.AddMicrosoftGraph();
var serviceProvider = tokenAcquirerFactory.Build();
// Call Microsoft Graph
var graphClient = serviceProvider.GetRequiredService<GraphServiceClient>();
var users = await graphClient.Users.GetAsync();
長所:
- 最小定型コード
- 自動的に読み込まれる
appsettings.json - 単純なシナリオに最適
- 1 行の初期化
欠点:
- 並列 (シングルトン) で実行されているテストには適していません
オプション 2: Full ServiceCollection (運用環境に推奨)
次の場合に最適です。 運用アプリケーション、複雑なシナリオ、依存関係の挿入、テスト可能性。
次のコードでは、.NET 汎用ホストを使用して、認証、トークン取得、キャッシュ、およびバックグラウンド サービスを構成します。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// Configure authentication
services.Configure<MicrosoftIdentityApplicationOptions>(
context.Configuration.GetSection("AzureAd"));
// Add token acquisition (true = singleton lifetime)
services.AddTokenAcquisition(true);
// Add token cache (in-memory for development)
services.AddInMemoryTokenCaches();
// Add HTTP client for API calls
services.AddHttpClient();
// Add Microsoft Graph (optional)
services.AddMicrosoftGraph();
// Add your background service
services.AddHostedService<DaemonWorker>();
})
.Build();
await host.RunAsync();
長所:
- 構成プロバイダーを完全に制御する
- コンストラクターの挿入によるテスト性の向上
- ASP.NET Core ホスティング モデルとの統合
- 複雑なシナリオ (複数の認証スキーム) をサポートします
- 運用対応アーキテクチャ
- 並列テスト実行をサポートします (テストごとに分離されたサービス プロバイダー)
注
trueでAddTokenAcquisition(true)パラメーターは、サービスがシングルトン (アプリの有効期間の単一インスタンス) として登録されていることを意味します。 Web アプリケーションでスコープ付き有効期間に false を使用します。
推薦: プロトタイプとシングルスレッド テストの
TokenAcquirerFactoryから始めます。 運用アプリケーションをビルドするとき、または並列テストを実行する場合は、完全なServiceCollectionパターンに移行します。
標準デーモン アプリケーションを構成する
標準デーモン アプリケーションは 、クライアント資格情報 (クライアント シークレットまたは証明書) を使用して認証し、API を呼び出す アプリ専用アクセス トークン を取得します。
認証設定を構成する
appsettings.json ファイルに次の構成を追加します。 クライアント シークレットまたは証明書 (運用環境に推奨) を使用できます。
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"ClientCredentials": [
// Option 1: Client Secret
{
"SourceType": "ClientSecret",
"ClientSecret": "your-client-secret",
},
// Option 2: Certificate (recommended for production)
{
"SourceType": "StoreWithDistinguishedName",
"CertificateStorePath": "CurrentUser/My",
"CertificateDistinguishedName": "CN=DaemonAppCert"
}
// More options: https://aka.ms/ms-id-web/client-credentials
]
}
}
大事な: 出力ディレクトリにコピーするように appsettings.json を設定します。
.csproj ファイルに次を追加します。
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
ASP.NET Coreアプリケーションはこのファイルを自動的にコピーしますが、デーモン アプリ (および OWIN アプリ) はコピーしません。
サービス構成を設定する
次のProgram.cs コードは、Microsoft Identity オプション、トークン取得、キャッシング、ホストされたバックグラウンド サービスを登録します。
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
IConfiguration configuration = context.Configuration;
// Configure Microsoft Identity options
services.Configure<MicrosoftIdentityApplicationOptions>(
configuration.GetSection("AzureAd"));
// Add token acquisition (true = singleton)
services.AddTokenAcquisition(true);
// Add token cache
services.AddInMemoryTokenCaches(); // For development
// services.AddDistributedTokenCaches(); // For production
// Add HTTP client
services.AddHttpClient();
// Add Microsoft Graph SDK (optional)
services.AddMicrosoftGraph();
// Add your background service
services.AddHostedService<DaemonWorker>();
})
.Build();
await host.RunAsync();
Microsoft Graph を呼び出す
次の DaemonWorker.cs クラスでは、Graph SDK を使用して、定期的なスケジュールでユーザーを一覧表示します。
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Graph;
using Microsoft.Identity.Abstractions;
public class DaemonWorker : BackgroundService
{
private readonly GraphServiceClient _graphClient;
private readonly ILogger<DaemonWorker> _logger;
public DaemonWorker(
GraphServiceClient graphClient,
ILogger<DaemonWorker> logger)
{
_graphClient = graphClient;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
// Call Microsoft Graph with app-only permissions
var users = await _graphClient.Users
.GetAsync(cancellationToken: stoppingToken);
_logger.LogInformation($"Found {users?.Value?.Count} users");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error calling Microsoft Graph");
}
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
}
}
}
IAuthorizationHeaderProvider を使用する
HTTP 呼び出しをより詳細に制御するには、 IAuthorizationHeaderProvider を使用して承認ヘッダーを手動で作成します。
using Microsoft.Identity.Abstractions;
public class DaemonService
{
private readonly IAuthorizationHeaderProvider _authProvider;
private readonly HttpClient _httpClient;
public DaemonService(
IAuthorizationHeaderProvider authProvider,
IHttpClientFactory httpClientFactory)
{
_authProvider = authProvider;
_httpClient = httpClientFactory.CreateClient();
}
public async Task<string> CallApiAsync()
{
// Get authorization header for app-only access
string authHeader = await _authProvider
.CreateAuthorizationHeaderForAppAsync(
scopes: "https://graph.microsoft.com/.default");
// Add to HTTP request
_httpClient.DefaultRequestHeaders.Clear();
_httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
var response = await _httpClient.GetStringAsync(
"https://graph.microsoft.com/v1.0/users");
return response;
}
}
ダウンストリーム API の呼び出しを参照して、Microsoft Identity Web がダウンストリーム API を呼び出す方法のすべてについて学んでください。
自律エージェントの構成 (エージェント ID)
自律エージェントは 、エージェント ID を 使用してアプリ専用トークンを取得します。 このパターンは、Copilotシナリオや自律サービスに役立ちます。
注
Microsoftでは、ダウンストリーム API を呼び出すエージェントは、エージェントがアプリ トークンを取得した場合でも、保護された Web API 内からそうすることをお勧めします。
エージェント サービスを構成する
次のコードでは、インメモリ構成を使用して、認証、トークン取得、およびエージェント ID のサポートを設定します。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Web;
var services = new ServiceCollection();
// Configuration
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["AzureAd:Instance"] = "https://login.microsoftonline.com/",
["AzureAd:TenantId"] = "your-tenant-id",
["AzureAd:ClientId"] = "your-agent-app-client-id",
["AzureAd:ClientCredentials:0:SourceType"] = "StoreWithDistinguishedName",
["AzureAd:ClientCredentials:0:CertificateStorePath"] = "CurrentUser/My",
["AzureAd:ClientCredentials:0:CertificateDistinguishedName"] = "CN=YourCert"
})
.Build();
services.AddSingleton<IConfiguration>(configuration);
// Configure Microsoft Identity
services.Configure<MicrosoftIdentityApplicationOptions>(
configuration.GetSection("AzureAd"));
services.AddTokenAcquisition(true);
services.AddInMemoryTokenCaches();
services.AddHttpClient();
services.AddMicrosoftGraph();
// Add agent identities support
services.AddAgentIdentities();
var serviceProvider = services.BuildServiceProvider();
エージェント ID を使用してトークンを取得する
エージェント サービスを構成した後、IAuthorizationHeaderProvider または Microsoft Graph SDK を使用してトークンを取得します。
using Microsoft.Identity.Abstractions;
using Microsoft.Graph;
// Your agent identity GUID
string agentIdentityId = "d84da24a-2ea2-42b8-b5ab-8637ec208024";
// Option 1: Using IAuthorizationHeaderProvider
IAuthorizationHeaderProvider authProvider =
serviceProvider.GetRequiredService<IAuthorizationHeaderProvider>();
var options = new AuthorizationHeaderProviderOptions()
.WithAgentIdentity(agentIdentityId);
string authHeader = await authProvider.CreateAuthorizationHeaderForAppAsync(
scopes: "https://graph.microsoft.com/.default",
options);
// Option 2: Using Microsoft Graph SDK
GraphServiceClient graphClient =
serviceProvider.GetRequiredService<GraphServiceClient>();
var applications = await graphClient.Applications.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(authOptions =>
{
authOptions.WithAgentIdentity(agentIdentityId);
});
});
完全な自律エージェントの例を確認する
次のクラスは、エージェント ID トークンの取得とGraph API呼び出しを再利用可能なサービスにラップします。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Graph;
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
public class AutonomousAgentService
{
private readonly GraphServiceClient _graphClient;
private readonly IAuthorizationHeaderProvider _authProvider;
private readonly string _agentIdentityId;
public AutonomousAgentService(
string agentIdentityId,
IServiceProvider serviceProvider)
{
_agentIdentityId = agentIdentityId;
_graphClient = serviceProvider.GetRequiredService<GraphServiceClient>();
_authProvider = serviceProvider.GetRequiredService<IAuthorizationHeaderProvider>();
}
public async Task<string> GetAuthorizationHeaderAsync()
{
var options = new AuthorizationHeaderProviderOptions()
.WithAgentIdentity(_agentIdentityId);
return await _authProvider.CreateAuthorizationHeaderForAppAsync(
"https://graph.microsoft.com/.default",
options);
}
public async Task<IEnumerable<Application>> ListApplicationsAsync()
{
var apps = await _graphClient.Applications.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
{
options.WithAgentIdentity(_agentIdentityId);
});
});
return apps?.Value ?? Enumerable.Empty<Application>();
}
}
エージェント ユーザー ID の構成
エージェント ユーザー ID を使用すると、エージェントは委任されたアクセス許可を持つ エージェント ユーザーに代わって 動作できます。 このパターンは、独自のメールボックスまたはその他のユーザー スコープ リソースを必要とするエージェントに使用します。
前提条件
エージェント ユーザー ID を使用するには、次のものが必要です。
- Microsoft Entra IDに登録されているエージェント ブループリント
- エージェント識別子が作成され、エージェント アプリケーションにリンクされました
- エージェント ID に関連付けられているエージェント ユーザー ID
エージェント ユーザー サービスを構成する
次のコードでは、証明書資格情報を使用してエージェント アプリケーション ID を構成し、必要なサービスを登録します。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Web;
using System.Security.Cryptography.X509Certificates;
var services = new ServiceCollection();
// Configure agent application
services.Configure<MicrosoftIdentityApplicationOptions>(options =>
{
options.Instance = "https://login.microsoftonline.com/";
options.TenantId = "your-tenant-id";
options.ClientId = "your-agent-app-client-id";
// Use certificate for agent authentication
options.ClientCredentials = new[]
{
CertificateDescription.FromStoreWithDistinguishedName(
"CN=YourCertificate",
StoreLocation.CurrentUser,
StoreName.My)
};
});
// Add services (true = singleton)
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
services.AddTokenAcquisition(true);
services.AddInMemoryTokenCaches();
services.AddHttpClient();
services.AddMicrosoftGraph();
services.AddAgentIdentities();
var serviceProvider = services.BuildServiceProvider();
エージェント ID を使用してユーザー トークンを取得する
ターゲット ユーザーは UPN またはオブジェクト ID で識別できます。
ユーザー名(UPN)による
using Microsoft.Identity.Abstractions;
using Microsoft.Graph;
string agentIdentityId = "your-agent-identity-id";
string userUpn = "user@yourtenant.onmicrosoft.com";
// Get authorization header
IAuthorizationHeaderProvider authProvider =
serviceProvider.GetRequiredService<IAuthorizationHeaderProvider>();
var options = new AuthorizationHeaderProviderOptions()
.WithAgentUserIdentity(
agentApplicationId: agentIdentityId,
username: userUpn);
string authHeader = await authProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "https://graph.microsoft.com/.default" },
options);
// Or use Microsoft Graph SDK
GraphServiceClient graphClient =
serviceProvider.GetRequiredService<GraphServiceClient>();
var me = await graphClient.Me.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
options.WithAgentUserIdentity(agentIdentityId, userUpn));
});
ユーザー オブジェクト ID による
string agentIdentityId = "your-agent-identity-id";
Guid userObjectId = Guid.Parse("user-object-id");
var options = new AuthorizationHeaderProviderOptions()
.WithAgentUserIdentity(
agentApplicationId: agentIdentityId,
userId: userObjectId);
string authHeader = await authProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "https://graph.microsoft.com/.default" },
options);
// With Graph SDK
var me = await graphClient.Me.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
options.WithAgentUserIdentity(agentIdentityId, userObjectId));
});
ClaimsPrincipal を使用してトークンをキャッシュする
パフォーマンスを向上させるには、 ClaimsPrincipal インスタンスを渡してユーザー トークンをキャッシュします。 最初の呼び出しでは、プリンシパルに uid 要求と utid 要求が設定されます。後続の呼び出しでは、キャッシュされたトークンが再利用されます。
using System.Security.Claims;
using Microsoft.Identity.Abstractions;
// First call - creates cache entry
ClaimsPrincipal userPrincipal = new ClaimsPrincipal();
string authHeader = await authProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "https://graph.microsoft.com/.default" },
options,
userPrincipal);
// ClaimsPrincipal now has uid and utid claims for caching
bool hasUserId = userPrincipal.HasClaim(c => c.Type == "uid");
bool hasTenantId = userPrincipal.HasClaim(c => c.Type == "utid");
// Subsequent calls - uses cache
authHeader = await authProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "https://graph.microsoft.com/.default" },
options,
userPrincipal); // Reuse the same principal
テナントをオーバーライドする
マルチテナント シナリオでは、実行時にテナントをオーバーライドできます。 これは、アプリが "common" で構成されているが、特定のテナントをターゲットにする必要がある場合に便利です。
var options = new AuthorizationHeaderProviderOptions()
.WithAgentUserIdentity(agentIdentityId, userUpn);
// Override tenant (useful when app is configured with "common")
options.AcquireTokenOptions.Tenant = "specific-tenant-id";
string authHeader = await authProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "https://graph.microsoft.com/.default" },
options);
// With Graph SDK
var me = await graphClient.Me.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
{
options.WithAgentUserIdentity(agentIdentityId, userUpn);
options.AcquireTokenOptions.Tenant = "specific-tenant-id";
});
});
完全なエージェント ユーザー ID の例を確認する
次のクラスは、エージェント ユーザー ID を使用してユーザー プロファイルと承認ヘッダーを取得するメソッドを提供します。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Graph;
using Microsoft.Identity.Abstractions;
using System.Security.Claims;
public class AgentUserService
{
private readonly IAuthorizationHeaderProvider _authProvider;
private readonly GraphServiceClient _graphClient;
private readonly string _agentIdentityId;
public AgentUserService(
string agentIdentityId,
IServiceProvider serviceProvider)
{
_agentIdentityId = agentIdentityId;
_authProvider = serviceProvider.GetRequiredService<IAuthorizationHeaderProvider>();
_graphClient = serviceProvider.GetRequiredService<GraphServiceClient>();
}
public async Task<User> GetUserProfileAsync(string userUpn)
{
var me = await _graphClient.Me.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
options.WithAgentUserIdentity(_agentIdentityId, userUpn));
});
return me!;
}
public async Task<User> GetUserProfileByIdAsync(Guid userObjectId)
{
var me = await _graphClient.Me.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
options.WithAgentUserIdentity(_agentIdentityId, userObjectId));
});
return me!;
}
public async Task<string> GetAuthHeaderForUserAsync(
string userUpn,
ClaimsPrincipal? cachedPrincipal = null)
{
var options = new AuthorizationHeaderProviderOptions()
.WithAgentUserIdentity(_agentIdentityId, userUpn);
return await _authProvider.CreateAuthorizationHeaderForUserAsync(
scopes: new[] { "https://graph.microsoft.com/.default" },
options,
cachedPrincipal ?? new ClaimsPrincipal());
}
}
再利用可能なサービス構成を作成する
拡張メソッドを定義する
アプリケーション全体でエージェント ID 構成をカプセル化する再利用可能な拡張メソッドを作成します。
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.InMemory;
public static class ServiceCollectionExtensions
{
public static IServiceProvider ConfigureServicesForAgentIdentities(
this IServiceCollection services,
IConfiguration configuration)
{
// Add configuration
services.AddSingleton(configuration);
// Configure Microsoft Identity options
services.Configure<MicrosoftIdentityApplicationOptions>(
configuration.GetSection("AzureAd"));
services.AddTokenAcquisition(true);
// Add token caching
services.AddInMemoryTokenCaches();
// Add HTTP client
services.AddHttpClient();
// Add Microsoft Graph (optional)
services.AddMicrosoftGraph();
// Add agent identities support
services.AddAgentIdentities();
return services.BuildServiceProvider();
}
}
拡張メソッドを使用する
拡張メソッドを呼び出して、1 行でサービスを構成します。
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var serviceProvider = services.ConfigureServicesForAgentIdentities(configuration);
API の呼び出し
このセクションでは、3 つの認証パターンをそれぞれ使用して API を呼び出す方法を示します。
Microsoft Graph を呼び出す
次の例では、標準デーモン、自律エージェント、およびエージェント ユーザー ID としてMicrosoft Graphを呼び出す方法を示します。
using Microsoft.Graph;
GraphServiceClient graphClient =
serviceProvider.GetRequiredService<GraphServiceClient>();
// Standard daemon (app-only)
var users = await graphClient.Users.GetAsync();
// Autonomous agent (app-only with agent identity)
var apps = await graphClient.Applications.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
{
options.WithAgentIdentity("agent-identity-id");
options.RequestAppToken = true;
});
});
// Agent user identity (delegated with user context)
var me = await graphClient.Me.GetAsync(request =>
{
request.Options.WithAuthenticationOptions(options =>
options.WithAgentUserIdentity("agent-identity-id", "user@tenant.com"));
});
IDownstreamApi を使用してカスタム API を呼び出す
IDownstreamApiを使用して、次の 3 つの認証パターンのいずれかで独自の保護された API を呼び出します。
using Microsoft.Identity.Abstractions;
IDownstreamApi downstreamApi =
serviceProvider.GetRequiredService<IDownstreamApi>();
// Standard daemon
var result = await downstreamApi.GetForAppAsync<ApiResponse>(
serviceName: "MyApi",
options => options.RelativePath = "api/data");
// With agent identity
var result = await downstreamApi.GetForAppAsync<ApiResponse>(
serviceName: "MyApi",
options =>
{
options.RelativePath = "api/data";
options.WithAgentIdentity("agent-identity-id");
});
// Agent user identity
var result = await downstreamApi.GetForUserAsync<ApiResponse>(
serviceName: "MyApi",
options =>
{
options.RelativePath = "api/data";
options.WithAgentUserIdentity("agent-identity-id", "user@tenant.com");
});
手動の HTTP 呼び出しを行う
HTTP 要求を完全に制御する必要がある場合は、 IAuthorizationHeaderProvider を直接使用します。
using Microsoft.Identity.Abstractions;
IAuthorizationHeaderProvider authProvider =
serviceProvider.GetRequiredService<IAuthorizationHeaderProvider>();
HttpClient httpClient = new HttpClient();
// Standard daemon
string authHeader = await authProvider.CreateAuthorizationHeaderForAppAsync(
"https://graph.microsoft.com/.default");
httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
var response = await httpClient.GetStringAsync("https://graph.microsoft.com/v1.0/users");
// With agent identity
var options = new AuthorizationHeaderProviderOptions()
.WithAgentIdentity("agent-identity-id");
authHeader = await authProvider.CreateAuthorizationHeaderForAppAsync(
"https://graph.microsoft.com/.default",
options);
// Agent user identity
var userOptions = new AuthorizationHeaderProviderOptions()
.WithAgentUserIdentity("agent-identity-id", "user@tenant.com");
authHeader = await authProvider.CreateAuthorizationHeaderForUserAsync(
new[] { "https://graph.microsoft.com/.default" },
userOptions);
トークン キャッシュの構成
環境に基づいてキャッシュ戦略を選択します。
開発: メモリ内キャッシュ
ローカルの開発とテストには、メモリ内キャッシュを使用します。
services.AddInMemoryTokenCaches();
プロダクション: 分散キャッシュ
運用環境では、分散キャッシュを使用して、アプリの再起動とスケールアウト インスタンス間でトークンを保持します。
SQL Server
SQL Server テーブルにトークンを格納します。
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = configuration["ConnectionStrings:TokenCache"];
options.SchemaName = "dbo";
options.TableName = "TokenCache";
});
services.AddDistributedTokenCaches();
Redis
Redis を使用して、高パフォーマンスの分散トークン キャッシュを行います。
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = configuration["Redis:ConnectionString"];
options.InstanceName = "TokenCache_";
});
services.AddDistributedTokenCaches();
Cosmos DB
グローバル分散トークン キャッシュには Cosmos DB を使用します。
services.AddCosmosDbTokenCaches(options =>
{
options.CosmosDbConnectionString = configuration["CosmosDb:ConnectionString"];
options.DatabaseId = "TokenCache";
options.ContainerId = "Tokens";
});
詳細情報:トークン キャッシュの構成
Azureサンプルを調べる
Microsoftでは、デーモン アプリのパターンを示すサンプルを提供します。
サンプル リポジトリ
active-directory-dotnetcore-daemon-v2
このリポジトリには、複数のシナリオが含まれています。
| サンプル | 説明 | リンク |
|---|---|---|
| 1-Call-MSGraph | クライアント資格情報を使用したデーモンによるMicrosoft Graphの基本的な呼び出し | サンプルを表示 |
| 2-Call-OwnApi | 独自の保護された Web API を呼び出すデーモン | サンプルを表示 |
| 3-Using-KeyVault | 証明書ストレージにAzure Key Vaultを使用するデーモン | サンプルを表示 |
| 4-マルチテナント | マルチテナント デーモン アプリケーション | サンプルを表示 |
| 5-Call-MSGraph-ManagedIdentity | Azureでマネージド ID を使用するデーモン | サンプルを表示 |
サンプル パターンと運用パターンを比較する
Azure サンプルでは、TokenAcquirerFactory.GetDefaultInstance()を使ってわかりやすくします。これは、simple コンソール アプリ、プロトタイプ、テストに推奨されるアプローチです。 このガイドでは、両方のパターンを示します。
TokenAcquirerFactory パターン (Azure サンプル):
// Simple, perfect for prototypes and tests
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi("MyApi", ...);
var serviceProvider = tokenAcquirerFactory.Build();
Full ServiceCollection パターン (運用アプリ):
// More control, testable, follows DI best practices
var services = new ServiceCollection();
services.AddTokenAcquisition(true); // true = singleton
services.Configure<MicrosoftIdentityApplicationOptions>(...);
var serviceProvider = services.BuildServiceProvider();
使用するタイミング:
を使用する: コンソール アプリ、迅速プロトタイプ、単体テスト、単純なデーモン サービス -
ServiceCollection
どちらの方法も完全にサポートされ、運用環境に対応しています。 アプリケーションの複雑さと統合のニーズに基づいて選択します。
一般的なエラーのトラブルシューティング
AADSTS700016: アプリケーションが見つかりません
原因: 無効な ClientId またはアプリケーションがテナントに登録されていません。
Solution: 構成の ClientId がMicrosoft Entra アプリの登録と一致するかどうかを確認します。
AADSTS7000215: クライアント シークレットが無効です
原因: クライアント シークレットが正しくない、期限切れ、または構成されていない。
Solution:
- Azure ポータルのシークレットが構成と一致するかどうかを確認する
- シークレットの有効期限を確認する
- 運用環境での証明書の使用を検討する
AADSTS700027: クライアント アサーションに無効な署名が含まれています
原因: 証明書が見つからない、期限切れ、秘密キーにアクセスできない。
Solution:
- 証明書が正しい証明書ストアにインストールされていることを確認する
- 証明書の識別名が構成と一致するかどうかを確認する
- アプリケーションに秘密キーを読み取るアクセス許可があることを確認する
- 証明書構成ガイドを参照してください
AADSTS650052: アプリがサービスにアクセスする必要がある
原因: 必要な API アクセス許可が付与されていないか、管理者の同意がありません。
Solution:
- Azure ポータル → アプリの登録 → アプリ → API のアクセス許可
- 必要なアクセス許可を追加する (例:
User.Read.Allfor Microsoft Graph) - [管理者の同意を付与する] ボタンをクリックします
エージェント ID エラー
AADSTS50105: サインインしているユーザーがロールに割り当てられない
原因: エージェント ID が正しく構成されていないか、アプリケーションに割り当てされていません。
Solution:
- Microsoft Entra IDにエージェント ID が存在するかどうかを確認する
- エージェント ID がアプリケーションにリンクされていることを確認する
- エージェント ID に必要なアクセス許可があることを確認する
トークンが取得されましたが、アクセス許可が間違っています
原因: エージェント ユーザー ID を使用するが、アプリのアクセス許可を要求する、またはその逆。
Solution:
-
アプリ専用トークンの場合、
CreateAuthorizationHeaderForAppAsyncとWithAgentIdentityを使用する。 -
委任されたトークンの場合:
CreateAuthorizationHeaderForUserAsyncと一緒にWithAgentUserIdentityを使用する - API のアクセス許可がトークンの種類と一致していることを確認する (アプリケーションと委任)
トークン キャッシュの問題
問題: トークンはキャッシュされないため、毎回新しい取得が強制されます。
Solution:
- エージェント ユーザー ID の場合: 呼び出し間で同じ
ClaimsPrincipalインスタンスを再利用する - 分散キャッシュ接続を確認する (Redis/SQL を使用している場合)
- デバッグ ログを有効にしてキャッシュ操作を表示する
詳細な診断:ログ記録と診断ガイド
関連するコンテンツ
- Web API からのダウンストリーム API の呼び出し - OBO パターン
- MSAL.NET フレームワーク ガイド - .NET Framework のトークン キャッシュと証明書の構成
- Certificate 構成 - Key Vault、ストア、ファイル、または Base64 からの証明書の読み込み
- トークン キャッシュの構成 - 運用キャッシュ戦略
- ログと診断 - トークン取得に関する問題の トラブルシューティング
- カスタマイズ ガイド - 高度な構成パターン
- Microsoft ID プラットフォーム のデーモンアプリケーションに関するドキュメント
- Azure サンプル: デーモン アプリケーション
- Microsoft。Identity.Web NuGet パッケージ
- Microsoft。Identity.Abstractions API リファレンス