Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье вы создадите приложения управляющей программы, фоновые службы и автономные агенты с помощью Microsoft. Identity.Web. Эти приложения выполняются без взаимодействия пользователя и проверки подлинности с помощью удостоверения приложения (учетные данные клиента) или удостоверений агента.
Общие сведения о поддерживаемых сценариях
Microsoft. Identity.Web поддерживает три типа неинтерактивных приложений:
| Сценарий | Тип проверки подлинности | Тип токена | Вариант использования |
|---|---|---|---|
| Стандартная управляющая программа | Учетные данные клиента (секрет или сертификат) | Маркер доступа только для приложений | Фоновые службы, запланированные задания, обработка данных |
| Автономный агент | Удостоверение агента с учетными данными клиента | Маркер доступа только для приложения для агента | Агенты Copilot, автономные службы, действующие от имени агентской идентичности. (Обычно в защищенном веб-API) |
| Удостоверение пользователя агента | Удостоверение пользователя агента | Удостоверение пользователя агента с учетными данными клиента | Автономные службы, действующие от имени идентификатора пользователя агента. (Обычно в защищенном веб-API) |
Начало работы
Необходимые условия
Прежде чем начать, убедитесь, что у вас есть:
- .NET 8.0 или более поздней версии
- Регистрация приложения в Microsoft Entra с использованием клиентских учетных данных (клиентский секрет или сертификат)
- Для сценариев агента: удостоверения агента, настроенные в клиенте Microsoft Entra
Установка пакетов
Добавьте необходимые пакеты NuGet в проект:
dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Extensions.Hosting
Выбор подхода к конфигурации
Microsoft. Identity.Web предоставляет два способа настройки приложений управляющей программы:
Вариант 1. TokenAcquirerFactory (рекомендуется для простых сценариев)
Лучше всего: Быстрые прототипы, консольные приложения, тестирование и простые службы управляющей программы.
Следующий код создает TokenAcquirerFactory, настраивает подчиненные API и Microsoft Graph и вызывает API Graph:
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 - Идеально подходит для простых сценариев
- Однострочная инициализация
Недостатки:
- Не подходит для тестов, выполняемых параллельно (одноэлементный)
Вариант 2. Полная коллекция услуг 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) означает, что служба регистрируется как синглтон (один экземпляр для времени существования приложения). Используйте 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 чтобы узнать обо всех способах вызова зависимых API через Microsoft Identity Web.
Настройка автономных агентов (идентичность агента)
Автономные агенты используют идентичности агента для получения токенов, предназначенных только для приложений. Этот шаблон полезен для сценариев Copilot и автономных служб.
Замечание
Microsoft рекомендует, чтобы агенты, вызывающие вторичные API, делали это из защищенных веб-API, даже если агенты получают токен приложения.
Настройка служб агента
Следующий код настраивает аутентификацию, получение токенов и поддержку идентификации агента с помощью конфигурации в памяти.
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();
Получение токенов с использованием идентификации агента
После настройки служб агента получите токены с помощью 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);
});
});
Просмотрите полный пример автономного агента
Следующий класс оборачивает процесс получения токена идентификации агента и вызовы API Graph в повторно используемую службу.
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>();
}
}
Настройка идентификации пользователя агента
Удостоверение пользователя агента позволяет агентам действовать от имени пользователя агента с делегированными разрешениями. Используйте этот шаблон для агентов, которым требуются собственные почтовые ящики или другие ресурсы с областью действия пользователя.
Необходимые условия
Чтобы использовать удостоверение пользователя агента, вам потребуется:
- Схема агента, зарегистрированная в Microsoft Entra 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();
Получение токенов пользователей, используя идентификацию агента
Вы можете определить целевого пользователя по имени пользователя или идентификатору объекта.
По имени пользователя (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));
});
По идентификатору объекта пользователя
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. Первый вызов заполняет субъект и uidutid утверждения; последующие вызовы повторно используют кэшированный токен:
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";
});
});
Просмотрите полный пример удостоверения пользователя агента
Следующий класс предоставляет методы для получения профилей пользователей и заголовков авторизации с помощью удостоверения пользователя агента:
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());
}
}
Создание конфигурации повторно используемых служб
Определение метода расширения
Создайте повторно используемый метод расширения, чтобы инкапсулировать конфигурацию удостоверения агента в приложении:
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();
}
}
Использование метода расширения
Вызовите метод расширения для настройки служб в одной строке:
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var serviceProvider = services.ConfigureServicesForAgentIdentities(configuration);
Вызов API-интерфейсов
В этом разделе показано, как вызывать API с помощью каждого из трех шаблонов проверки подлинности.
Подключение к Microsoft Graph
В следующих примерах демонстрируется вызов 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"));
});
Вызов пользовательских API с помощью IDownstreamApi
Используйте IDownstreamApi для вызова собственных защищенных 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 вручную
Используйте IAuthorizationHeaderProvider непосредственно, если требуется полный контроль над HTTP-запросами:
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 для высокопроизводительного кэширования распределенных токенов:
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 | Демон вызывает ваши собственные защищенные веб-API | Посмотреть образец |
| 3-Using-KeyVault | Демон, использующий Azure Key Vault для хранения сертификатов | Посмотреть образец |
| 4-Multi-Tenant | Мультитенантное приложение-демон | Посмотреть образец |
| 5-Call-MSGraph-ManagedIdentity | Демон, использующий управляемое удостоверение в Azure | Посмотреть образец |
Сравнение примеров шаблонов с рабочими шаблонами
Примеры Azure используют TokenAcquirerFactory.GetDefaultInstance() для простоты — как рекомендованный подход для простых консольных приложений, прототипов и тестов. В этом руководстве показаны оба шаблона:
Шаблон 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();
Когда следует использовать:
-
Использовать
TokenAcquirerFactoryдля: консольные приложения, быстрые прототипы, модульные тесты, простые службы управляющей программы -
Use
ServiceCollectionдля: производственных приложений, интеграции ASP.NET Core, сложных сценариев DI, фоновых служб сIHostedService
Оба подхода полностью поддерживаются и готовы к работе. Выберите в зависимости от сложности и интеграции приложения.
Устранение распространенных ошибок
AADSTS700016: приложение не найдено
Причина: Некорректный ClientId или приложение не зарегистрировано в клиенте.
Solution: Убедитесь, что ClientId в конфигурации соответствует регистрации приложения Microsoft Entra.
AADSTS7000215: недопустимый секрет клиента
Причина: Клиентский секрет неверен, истек или не настроен.
Solution:
- Убедитесь, что секрет на портале Azure соответствует вашей конфигурации.
- Проверка даты окончания срока действия секрета
- Рассмотрите возможность использования сертификатов для рабочей среды
AADSTS700027: утверждение клиента содержит недопустимую подпись
Причина: Сертификат не найден, истек срок действия или закрытый ключ недоступен.
Solution:
- Проверьте, установлен ли сертификат в правильном хранилище сертификатов.
- Проверьте, что уникальное имя сертификата соответствует конфигурации
- Убедитесь, что приложение имеет разрешение на чтение закрытого ключа
- См . руководство по настройке сертификата
AADSTS650052: приложению требуется доступ к службе
Причина: Не предоставлены необходимые разрешения API или отсутствует согласие администратора.
Solution:
- Перейдите на портал Azure → Регистрация приложений → ваше приложение → API-разрешения
- Добавление необходимых разрешений (например,
User.Read.Allдля Microsoft Graph) - Нажмите кнопку "Предоставить согласие администратора"
Ошибки идентификации агента
AADSTS50105: пользователь, вошедший в систему, не назначен на роль
Причина: Идентификация агента неправильно настроена или не назначена приложению.
Solution:
- Проверка наличия удостоверения агента в Microsoft Entra ID
- Убедитесь, что удостоверение личности агента связано с вашим приложением
- Убедитесь, что удостоверение агента имеет необходимые разрешения
Маркеры, приобретенные, но с неправильными разрешениями
Причина: Использование удостоверения агента, но запрос разрешений приложения (или наоборот).
Solution:
- Для маркеров, доступных только для приложений: использование
CreateAuthorizationHeaderForAppAsyncсWithAgentIdentity - Для делегированных маркеров: используйте
CreateAuthorizationHeaderForUserAsyncсWithAgentUserIdentity - Убедитесь, что разрешения API соответствуют типу токена (приложение или делегировано)
Проблемы с кэшированием токенов
Проблема: Токены не кэшируются, что вынуждает совершать новое приобретение каждый раз.
Solution:
- Для идентификации пользователя агента: используйте один и тот же экземпляр
ClaimsPrincipalдля всех вызовов - Проверка подключения распределенного кэша (при использовании Redis/SQL)
- Включение ведения журнала отладки для просмотра операций кэша
Подробное руководство по диагностике:ведение журнала и диагностика
Связанный контент
- Вызов зависимых API из веб-API — OBO-шаблоны
- < Руководство по платформе
MSAL.NET/c0> — кэш токенов и конфигурация сертификатов для платформы .NET Framework - конфигурация Certificate — загрузка сертификатов из Key Vault, хранилища, файла или Base64
- Конфигурация кэша маркеров — стратегии кэширования в рабочей среде
- Ведение журнала и диагностика - Устранение проблем с получением токенов
- Руководство по настройке — расширенные шаблоны конфигурации
- документация по приложению платформа удостоверений Майкрософт управляющая программа
- Azure Образцы: сервисные приложения
- Пакет Microsoft.Identity.Web для NuGet
- Microsoft.Identity.Abstractions: справочник по API