Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo, construyes aplicaciones daemon, servicios en segundo plano y agentes autónomos usando Microsoft.Identity.Web. Estas aplicaciones se ejecutan sin interacción del usuario y se autentican mediante identidades de aplicación (credenciales de cliente) o identidades de agente.
Descripción de los escenarios admitidos
Microsoft. Identity.Web admite tres tipos de aplicaciones no interactivas:
| Escenario | Tipo de autenticación | Tipo de token | Caso de uso |
|---|---|---|---|
| Demonio estándar | Credenciales de cliente (secreto/certificado) | Token de acceso de solo aplicación | Servicios en segundo plano, trabajos programados, procesamiento de datos |
| Agente autónomo | Identidad del agente con credenciales de cliente | Token de acceso de solo aplicación para el agente | Agentes Copilot, servicios autónomos que actúan en nombre de una identidad de agente. (Normalmente en una API web protegida) |
| Identidad de usuario del agente | Identidad de usuario del agente | Identidad de usuario del agente con credenciales de cliente | Servicios autónomos que actúan en nombre de una identidad de usuario agente. (Normalmente en una API web protegida) |
Comenzar
Prerrequisitos
Antes de comenzar, asegúrese de que tiene:
- .NET 8.0 o posterior
- Microsoft Entra registro de aplicaciones con credenciales de cliente (secreto de cliente o certificado)
- Para escenarios de agente: identidades de agente configuradas en el inquilino de Microsoft Entra
Instalación de paquetes
Agregue los paquetes NuGet necesarios al proyecto:
dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Extensions.Hosting
Elección de un enfoque de configuración
Microsoft.Identity.Web proporciona dos maneras de configurar aplicaciones de servicio:
Opción 1: TokenAcquirerFactory (recomendado para escenarios simples)
Lo mejor para: Prototipos rápidos, aplicaciones de consola, pruebas, y servicios en segundo plano simples.
El código siguiente crea un TokenAcquirerFactory, configura las API de bajada y Microsoft Graph y llama a la API de 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();
Ventajas:
- Código estándar mínimo
- Carga automáticamente
appsettings.json - Perfecto para escenarios sencillos
- Inicialización de una línea
Desventajas:
- No es adecuado para las pruebas que se ejecutan en paralelo (singleton)
Opción 2: Colección de Servicios completa (recomendado para producción)
Lo mejor para: Aplicaciones de producción, escenarios complejos, inserción de dependencias, capacidad de prueba.
El código siguiente usa el host genérico de .NET para configurar la autenticación, la adquisición de tokens, el almacenamiento en caché y un servicio en segundo plano:
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();
Ventajas:
- Control total sobre los proveedores de configuración
- Mejor capacidad de prueba con inserción de constructores
- Se integra con ASP.NET Core modelo de hospedaje
- Admite escenarios complejos (varios esquemas de autenticación)
- Arquitectura lista para producción
- Admite la ejecución de pruebas paralelas (proveedor de servicios aislado por prueba)
Nota:
El parámetro true de AddTokenAcquisition(true) significa que el servicio se registra como singleton (instancia única para la vida útil de la aplicación). Utilice false para la vida útil delimitada en aplicaciones web.
Recomendación: Comience con
TokenAcquirerFactorypara prototipos y pruebas de un solo subproceso. Migre al patrón completoServiceCollectional compilar aplicaciones de producción o ejecutar pruebas paralelas.
Configura aplicaciones de demonio estándar
Las aplicaciones de demonio estándar se autentican mediante credenciales de cliente (secreto de cliente o certificado) y obtienen tokens de acceso de solo aplicación para llamar a las API.
Configurar los ajustes de autenticación
Agregue la siguiente configuración al archivo appsettings.json . Puede usar un secreto de cliente o un certificado (recomendado para producción):
{
"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
]
}
}
Importante: Establezca su appsettings.json para copiar en el directorio de salida. Agregue lo siguiente al .csproj archivo:
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Las aplicaciones de ASP.NET Core copian este archivo automáticamente, pero las aplicaciones daemon (y las aplicaciones OWIN) no.
Configuración del servicio
El siguiente código Program.cs registra Microsoft opciones de identidad, adquisición de tokens, almacenamiento en caché y un servicio en segundo plano hospedado:
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();
Llame a Microsoft Graph
La siguiente clase DaemonWorker.cs usa el SDK de Graph para mostrar a los usuarios una programación periódica:
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);
}
}
}
Uso de IAuthorizationHeaderProvider
Para obtener más control sobre las llamadas HTTP, use IAuthorizationHeaderProvider para crear encabezados de autorización manualmente:
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;
}
}
Consulte también Llamadas a las API subyacentes para obtener información sobre todas las maneras en que Microsoft Identity Web propone llamar a las API de servidor.
Configuración de agentes autónomos (identidad del agente)
Los agentes autónomos usan identidades de agente para obtener tokens de solo aplicación. Este patrón es útil para escenarios de Copilot y servicios autónomos.
Nota:
Microsoft recomienda que los agentes que llaman a las API de bajada lo hagan desde las API web protegidas, incluso cuando los agentes adquieren un token de aplicación.
Configuración de servicios de agente
El código siguiente configura la autenticación, la adquisición de tokens y la compatibilidad con la identidad del agente mediante la configuración en memoria:
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();
Adquisición de tokens con la identidad del agente
Después de configurar los servicios del agente, adquiera tokens mediante IAuthorizationHeaderProvider o el SDK de Microsoft Graph:
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);
});
});
Revisión de un ejemplo completo de agente autónomo
La siguiente clase encapsula la adquisición de token de identidad del agente y llamadas a la API de Graph en un servicio reutilizable.
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>();
}
}
Configuración de la identidad de usuario del agente
La identidad de usuario del agente permite a los agentes actuar en nombre de un usuario del agente con permisos delegados. Use este patrón para los agentes que necesitan su propio buzón u otros recursos con ámbito de usuario.
Prerrequisitos
Para usar la identidad de usuario del agente, necesita:
- Plano técnico del agente registrado en Microsoft Entra ID
- Identidad del agente creada y vinculada a la aplicación del agente
- Identidad de usuario del agente asociada a la identidad del agente
Configuración de los servicios de usuario del agente
El código siguiente configura la identidad de la aplicación del agente con una credencial de certificado y registra los servicios necesarios:
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();
Adquisición de tokens de usuario con identidad de agente
Puede identificar el usuario de destino por UPN o identificador de objeto.
Por nombre de usuario (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));
});
Por identificador de objeto de usuario
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));
});
Almacenar tokens en caché con ClaimsPrincipal
Para mejorar el rendimiento, almacene en caché los tokens de usuario mediante una instancia ClaimsPrincipal. La primera llamada rellena la entidad de seguridad con las afirmaciones uid y utid; las llamadas posteriores reutilizan el token almacenado en caché.
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
Invalidación del inquilino
En escenarios multiinquilino, puede invalidar el inquilino en tiempo de ejecución. Esto resulta útil cuando la aplicación está configurada con "common" , pero debe tener como destino un inquilino específico:
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";
});
});
Revisión de un ejemplo completo de identidad de usuario del agente
La siguiente clase proporciona métodos para obtener perfiles de usuario y encabezados de autorización mediante la identidad de usuario del agente:
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());
}
}
Creación de una configuración de servicio reutilizable
Definición de un método de extensión
Cree un método de extensión reutilizable para encapsular la configuración de identidad del agente en toda la aplicación:
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();
}
}
Uso del método de extensión
Llame al método de extensión para configurar los servicios en una sola línea:
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var serviceProvider = services.ConfigureServicesForAgentIdentities(configuration);
Llamada a las API
En esta sección se muestra cómo llamar a las API mediante cada uno de los tres patrones de autenticación.
Llame a Microsoft Graph
En los ejemplos siguientes se muestra cómo llamar a Microsoft Graph como demonio estándar, un agente autónomo y una identidad de usuario del agente:
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"));
});
Llamada a API personalizadas con IDownstreamApi
Use IDownstreamApi para llamar a sus propias API protegidas con cualquiera de los tres patrones de autenticación:
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");
});
Realización de llamadas HTTP manuales
Use IAuthorizationHeaderProvider directamente cuando necesite control total sobre las solicitudes 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);
Configuración del almacenamiento en caché de tokens
Elija una estrategia de almacenamiento en caché basada en su entorno.
Desarrollo: caché en memoria
Use el almacenamiento en caché en memoria para el desarrollo y las pruebas locales:
services.AddInMemoryTokenCaches();
Producción: caché distribuida
En el caso de producción, use una caché distribuida para conservar los tokens entre los reinicios de la aplicación y las instancias de escalabilidad horizontal.
SQL Server
Almacenar tokens en una tabla de SQL Server:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = configuration["ConnectionStrings:TokenCache"];
options.SchemaName = "dbo";
options.TableName = "TokenCache";
});
services.AddDistributedTokenCaches();
Redis
Use Redis para el almacenamiento en caché de tokens distribuidos de alto rendimiento:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = configuration["Redis:ConnectionString"];
options.InstanceName = "TokenCache_";
});
services.AddDistributedTokenCaches();
Cosmos DB
Use Cosmos DB para el almacenamiento en caché de tokens distribuidos globalmente:
services.AddCosmosDbTokenCaches(options =>
{
options.CosmosDbConnectionString = configuration["CosmosDb:ConnectionString"];
options.DatabaseId = "TokenCache";
options.ContainerId = "Tokens";
});
Más información:Configuración de caché de tokens
Exploración de ejemplos de Azure
Microsoft proporciona ejemplos que muestran patrones de aplicaciones de servicio.
Repositorio de ejemplo
active-directory-dotnetcore-daemon-v2
Este repositorio contiene varios escenarios:
| Ejemplo | Descripción | Vínculo |
|---|---|---|
| 1-Call-MSGraph | Demonio básico llamando a Microsoft Graph con credenciales de cliente | Ver ejemplo |
| 2-Call-OwnApi | Demonio que llama a su propia API web protegida | Ver ejemplo |
| 3-Using-KeyVault | Daemon usando Azure Key Vault para el almacenamiento de certificados | Ver ejemplo |
| 4-Multiinquilino | Aplicación de servicio multiarrendatario | Ver ejemplo |
| 5-Call-MSGraph-ManagedIdentity | Demonio usando Identidad Administrada en Azure | Ver ejemplo |
Comparación de patrones de ejemplo con patrones de producción
Los ejemplos de Azure usan TokenAcquirerFactory.GetDefaultInstance() para simplificar: el enfoque recomendado para simple aplicaciones de consola, prototipos y pruebas. En esta guía se muestran ambos patrones:
Patrón TokenAcquirerFactory (muestras de Azure):
// Simple, perfect for prototypes and tests
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi("MyApi", ...);
var serviceProvider = tokenAcquirerFactory.Build();
Patrón completo de ServiceCollection (Aplicaciones de producción):
// More control, testable, follows DI best practices
var services = new ServiceCollection();
services.AddTokenAcquisition(true); // true = singleton
services.Configure<MicrosoftIdentityApplicationOptions>(...);
var serviceProvider = services.BuildServiceProvider();
Cuándo usar qué:
-
Uso
TokenAcquirerFactorypara: Aplicaciones de consola, prototipos rápidos, pruebas unitarias, servicios de demonio simples -
Use
ServiceCollectionpara: Aplicaciones de producción, integración ASP.NET Core, escenarios complejos de di, servicios en segundo plano conIHostedService
Ambos enfoques son totalmente compatibles y listos para producción. Elija en función de las necesidades de integración y complejidad de la aplicación.
Solución de errores comunes
AADSTS700016: no se encontró la aplicación
Causa: Aplicación no válida ClientId o no registrada en el arrendatario.
Solución: Verifique que el ClientId en su configuración coincida con el registro de la aplicación de Microsoft Entra.
AADSTS7000215: secreto de cliente no válido
Causa: El secreto de cliente es incorrecto, ha expirado o no está configurado.
Solution:
- Verifique que el secreto en Azure portal coincide con su configuración.
- Comprobación de la fecha de expiración del secreto
- Considere la posibilidad de usar certificados para producción
AADSTS700027: la aserción de cliente contiene una firma no válida
Causa: No se encuentra el certificado, ha expirado o no se puede acceder a la clave privada.
Solution:
- Comprobación de que el certificado está instalado en el almacén de certificados correcto
- Comprobar que el nombre distintivo del certificado coincide con la configuración
- Asegúrese de que la aplicación tiene permiso para leer la clave privada
- Consulte la Guía de configuración de certificados.
AADSTS650052: la aplicación necesita acceso a un servicio
Causa: Faltan los permisos de API necesarios o falta el consentimiento del administrador.
Solution:
- Vaya al portal de Azure → Registros de aplicaciones → Su aplicación → Permisos de la API
- Agregar permisos necesarios (por ejemplo,
User.Read.Allpara Microsoft Graph) - Haga clic en el botón "Conceder consentimiento del administrador"
Errores de identidad del agente
AADSTS50105: el usuario que ha iniciado sesión no está asignado a un rol
Causa: La identidad del agente no está configurada correctamente o no está asignada a la aplicación.
Solution:
- Compruebe que la identidad del agente existe en Microsoft Entra ID
- Asegúrese de que la identidad del agente esté vinculada a la aplicación.
- Verificar que la identidad del agente tiene los permisos necesarios.
Tokens adquiridos pero con permisos incorrectos
Causa: Usar la identidad de usuario del agente pero solicitar permisos de aplicación, o viceversa.
Solution:
- Para tokens de solo aplicación: uso
CreateAuthorizationHeaderForAppAsyncconWithAgentIdentity - Para tokens delegados: use
CreateAuthorizationHeaderForUserAsyncconWithAgentUserIdentity - Asegúrese de que los permisos de API coinciden con el tipo de token (aplicación frente a delegado)
Problemas de almacenamiento en caché de tokens
Problema: Los tokens no se almacenan en caché, lo que fuerza una nueva adquisición cada vez.
Solution:
- Para la identidad de usuario del agente: reutilización de la misma
ClaimsPrincipalinstancia entre llamadas - Comprobación de la conexión de caché distribuida (si usa Redis/SQL)
- Habilite el registro de depuración para ver las operaciones de caché
Diagnóstico detallado:Guía de registro y diagnóstico
Contenido relacionado
- Llamar a las API descendentes desde API Web - patrones de OBO
- Guía del marco MSAL.NET: caché de tokens y configuración de certificados para .NET Framework
- configuración de Certificate: carga de certificados desde Key Vault, almacén, archivo o Base64
- Configuración de caché de token: estrategias de caché en producción
- Registro y diagnóstico — solución de problemas de adquisición de tokens
- Guía de personalización : patrones de configuración avanzados
- Documentación de la plataforma Microsoft Identity para aplicaciones en segundo plano
- Azure Ejemplos: aplicaciones de servicio
- Paquete NuGet de Microsoft.Identity.Web
- Referencia de la API de Microsoft.Identity.Abstractions