Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa guida illustra come creare applicazioni daemon, servizi in background e agenti autonomi usando Microsoft. Identity.Web. Queste applicazioni vengono eseguite senza interazione dell'utente ed eseguono l'autenticazione usando l'identità dell'applicazione (credenziali client) o le identità dell'agente.
Informazioni generali
Microsoft. Identity.Web supporta tre tipi di applicazioni non interattive:
| Scenario | Tipo di autenticazione | Tipo di token | Caso d'uso |
|---|---|---|---|
| Standard Daemon | Credenziali client (segreto/certificato) | Token di accesso solo per app | Servizi in background, processi pianificati, elaborazione dati |
| Agente autonomo | Identità agente con credenziali client | Token di accesso solo per app per l'agente | Agenti Copilot, servizi autonomi che agiscono per conto di un'identità di agente. (in genere in un'API Web protetta) |
| Identità utente agente | Identità utente agente | Identità dell'utente agente con credenziali del client | Servizi autonomi che agiscono per conto di un'identità utente di Agent. (in genere in un'API Web protetta) |
Avvio rapido
Prerequisiti
- .NET 8.0 o versione successiva
- Microsoft Entra registrazione dell'app con credenziali del client (segreto della chiave client o certificato)
- Per scenari relativi agli agenti: identità dell'agente configurate nel tenant Microsoft Entra
Installazione
dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Extensions.Hosting
Due approcci di configurazione
Microsoft. Identity.Web offre due modi per configurare le applicazioni daemon:
Opzione 1: TokenAcquirerFactory (consigliato per scenari semplici)
Ideale per: Prototipi rapidi, app console, test e semplici servizi daemon.
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();
Vantaggi:
- Codice boilerplate minimo
- Carica automaticamente
appsettings.json - Perfetto per scenari semplici
- Inizializzazione in una riga
- Non adatto per i test in esecuzione in parallelo (singleton)
Opzione 2: Full ServiceCollection (scelta consigliata per l'ambiente di produzione)
Ideale per: Applicazioni di produzione, scenari complessi, inserimento delle dipendenze, testability.
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();
Vantaggi:
- Controllo completo sui provider di configurazione
- Maggiore testabilità con l'iniezione di costruttore
- Si integra con il modello di hosting di ASP.NET Core
- Supporta scenari complessi (più schemi di autenticazione)
- Architettura pronta per la produzione
- Supporta l'esecuzione parallela dei test (provider di servizi isolati per ciascun test)
Annotazioni
Il parametro true in AddTokenAcquisition(true) indica che il servizio viene registrato come singleton (istanza singola per la durata dell'app). Usare false per la durata con ambito nelle applicazioni Web.
Raccomandazione: Iniziare con
TokenAcquirerFactoryper i prototipi e i test a thread singolo. Eseguire la migrazione al modello completoServiceCollectiondurante la compilazione di applicazioni di produzione o l'esecuzione di test paralleli.
Applicazioni daemon standard
Le applicazioni daemon standard eseguono l'autenticazione usando credenziali client (segreto client o certificato) e ottengono token di accesso solo app per chiamare le API.
Configurazione
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
]
}
}
Importante: Imposta il tuo appsettings.json per copiare nella directory di output:
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Questa operazione viene eseguita automaticamente nelle applicazioni ASP.NET Core, ma non per le app daemon (o OWIN)
Configurazione del servizio (modello consigliato)
Program.cs:
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();
Chiamata di Microsoft Graph
DaemonWorker.cs:
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 di IAuthorizationHeaderProvider
Per un maggiore controllo sulle chiamate HTTP:
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;
}
}
Vedere anche Calling downstream API per informazioni su tutti i modi in cui Microsoft Identity Web propone di chiamare LE API downstream.
Agenti autonomi (identità agente)
Gli agenti autonomi usano le identità degli agenti per ottenere token esclusivi per l'app. Ciò è utile per gli scenari Copilot, i servizi autonomi.
Microsoft consiglia agli agenti di chiamare le API downstream nelle API Web protette anche se questi agenti autonomi acquisiranno un token dell'app
Configurazione
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();
Acquisizione di token con identità dell'agente
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);
});
});
Esempio completo dell'agente autonomo
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>();
}
}
Identità utente agente
L'identità utente agente consente agli agenti di agire per conto di un utente agente con autorizzazioni delegate. Questo è per gli agenti che hanno la propria cassetta postale, ecc ...
Prerequisiti
- Progetto agent registrato in Microsoft Entra ID
- Identità dell'agente creata e collegata all'applicazione agente
- Identità utente agente associata all'identità dell'agente
Configurazione
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();
Acquisizione di token utente con l'identità dell'agente
Per nome utente (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 oggetto utente
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));
});
Memorizzazione nella cache dei token con ClaimsPrincipal
Per prestazioni migliori, memorizzare nella cache i token utente usando ClaimsPrincipal:
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
Sovrascrittura del tenant
Per gli scenari multi-tenant, eseguire l'override del tenant in fase di esecuzione:
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";
});
});
Esempio completo di identità utente dell'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());
}
}
Configurazione del servizio
Modello di metodo di estensione (scelta consigliata)
Creare un metodo di estensione riutilizzabile per una configurazione coerente:
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();
}
}
Utilizzo
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var serviceProvider = services.ConfigureServicesForAgentIdentities(configuration);
Chiamata di API
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 personalizzate con IDownstreamApi
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");
});
Chiamate HTTP manuali
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);
Memorizzazione nella cache dei token
Sviluppo: cache in memoria
services.AddInMemoryTokenCaches();
Produzione: cache distribuita
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
services.AddCosmosDbTokenCaches(options =>
{
options.CosmosDbConnectionString = configuration["CosmosDb:ConnectionString"];
options.DatabaseId = "TokenCache";
options.ContainerId = "Tokens";
});
Altre informazioni:Configurazione della cache dei token
esempi di Azure
Microsoft fornisce esempi completi che illustrano i modelli di app daemon:
Repository di esempio
active-directory-dotnetcore-daemon-v2
Questo repository contiene più scenari:
| Esempio | Descrizione | Link |
|---|---|---|
| 1-Call-MSGraph | Daemon di base che chiama Microsoft Graph con credenziali client | Visualizza esempio |
| 2-Call-OwnApi | Daemon che chiama la tua API Web protetta | Visualizza esempio |
| 3-Using-KeyVault | Daemon con Azure Key Vault per l'archiviazione dei certificati | Visualizza esempio |
| 4-Multi-Tenant | Applicazione daemon multi-tenant | Visualizza esempio |
| 5-Call-MSGraph-ManagedIdentity | Daemon che usa l'identità gestita in Azure | Visualizza esempio |
Differenze principali rispetto agli esempi
Gli esempi di Azure usano TokenAcquirerFactory.GetDefaultInstance() per semplicità: questo è l'approccio consigliato per applicazioni console semplici, prototipi e test. Questa guida illustra entrambi i modelli:
Modello TokenAcquirerFactory (Azure Samples):
// Simple, perfect for prototypes and tests
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi("MyApi", ...);
var serviceProvider = tokenAcquirerFactory.Build();
Full ServiceCollection Pattern (per applicazioni di produzione):
// More control, testable, follows DI best practices
var services = new ServiceCollection();
services.AddTokenAcquisition(true); // true = singleton
services.Configure<MicrosoftIdentityApplicationOptions>(...);
var serviceProvider = services.BuildServiceProvider();
Quando usare quale:
-
Utilizzare
TokenAcquirerFactoryper: app console, prototipi rapidi, unit test, servizi daemon semplici -
Usare
ServiceCollectionper: applicazioni di produzione, integrazione ASP.NET Core, scenari di inserimento delle dipendenze complessi, servizi in background conIHostedService
Entrambi gli approcci sono completamente supportati e pronti per la produzione. Scegliere in base alle esigenze di complessità e integrazione dell'applicazione.
Risoluzione dei problemi
AADSTS700016: applicazione non trovata
Causa: Non valido ClientId o l'applicazione non è registrata nel tenant.
Solution: Verificare che il ClientId nella configurazione corrisponda alla registrazione dell'app Microsoft Entra.
AADSTS7000215: Client Secret non valido
Causa: Il segreto client non è corretto, è scaduto o non è configurato.
Soluzione:
- Verificare che il segreto nel portale di Azure corrisponda alla configurazione
- Controllare la data di scadenza del segreto
- Prendere in considerazione l'uso dei certificati per la produzione
AADSTS700027: l'asserzione client contiene una firma non valida
Causa: Certificato non trovato, scaduto o chiave privata non accessibile.
Soluzione:
- Verificare che il certificato sia installato nell'archivio certificati corretto
- Controllare che il nome distinto del certificato corrisponda alla configurazione
- Verificare che l'applicazione disponga dell'autorizzazione per leggere la chiave privata
- Vedere La Guida alla configurazione dei certificati
AADSTS650052: l'app deve accedere a un servizio
Causa: Autorizzazioni API necessarie non concesse o consenso amministratore mancante.
Soluzione:
- Passare al portale di Azure → Registrazioni app → Autorizzazioni API per l'app →
- Aggiungere le autorizzazioni necessarie (ad esempio,
User.Read.Allper Microsoft Graph) - Fare clic sul pulsante "Concedi consenso amministratore"
Errori dell'identità dell'agente
AADSTS50105: l'utente connesso non è assegnato a un ruolo
Causa: Identità dell'agente non configurata correttamente o non assegnata all'applicazione.
Soluzione:
- Verificare che l'identità dell'agente esista in Microsoft Entra ID
- Verificare che l'identità dell'agente sia collegata all'applicazione
- Verificare che l'identità dell'agente disponga delle autorizzazioni necessarie
Token acquisiti ma con autorizzazioni errate
Causa: Uso dell'identità utente dell'agente ma richiesta di autorizzazioni dell'app o viceversa.
Soluzione:
- Per token riservati ad app: usare
CreateAuthorizationHeaderForAppAsyncconWithAgentIdentity - Per i token delegati: usare
CreateAuthorizationHeaderForUserAsyncconWithAgentUserIdentity - Verificare che le autorizzazioni API corrispondano al tipo di token (applicazione e delegata)
Problemi di memorizzazione nella cache dei token
Problema: I token non vengono memorizzati nella cache, forzando ogni volta la nuova acquisizione.
Soluzione:
- Per l'identità utente dell'agente: riutilizzare la stessa
ClaimsPrincipalistanza tra le chiamate - Verificare la connessione alla cache distribuita (se si usa Redis/SQL)
- Abilitare la registrazione di debug per visualizzare le operazioni della cache
Diagnostica dettagliata:Guida alla registrazione e alla diagnostica
Contenuti correlati
- Chiamata di API downstream dalle API Web - Modelli OBO
- Guida al framework MSAL.NET - Configurazione della cache dei token e del certificato per .NET Framework
- Configurazione certificato - Caricamento di certificati da Key Vault, archivio, file o Base64
- Configurazione della cache dei token - Strategie di memorizzazione nella cache di produzione
- Registrazione e diagnostica - Risolvere i problemi di acquisizione dei token
- Guida alla personalizzazione - Modelli di configurazione avanzati
- Documentazione dell'applicazione daemon della piattaforma di identità Microsoft
- esempi di Azure: applicazioni daemon
- Microsoft.Identity.Web NuGet package
- Riferimento API Microsoft.Identity.Abstractions