Skapa daemonprogram och agentidentiteter med Microsoft. Identity.Web

I den här artikeln skapar du daemonprogram, bakgrundstjänster och autonoma agenter med hjälp av Microsoft. Identity.Web. Dessa program körs utan användarinteraktion och autentiseras med hjälp av programidentiteter (klientautentiseringsuppgifter) eller agentidentiteter.

Förstå scenarier som stöds

Microsoft. Identity.Web stöder tre typer av icke-interaktiva program:

Scenario Autentiseringstyp Tokentyp Användningsfall
Standard Daemon Klientautentiseringsuppgifter (hemlighet/certifikat) Åtkomsttoken endast för appar Bakgrundstjänster, schemalagda jobb, databehandling
Autonom agent Agentidentitet med klientautentiseringsuppgifter Åtkomsttoken endast för appar för agenten Copilot agenter, autonoma tjänster som agerar på uppdrag av en agentidentitet. (Vanligtvis i ett skyddat webb-API)
Agentens användaridentitet Agentanvändaridentitet Agentanvändaridentitet med klientautentiseringsuppgifter Autonoma tjänster som agerar på uppdrag av en agentanvändares identitet. (Vanligtvis i ett skyddat webb-API)

Kom igång

Förutsättningar

Innan du kan börja bör du kontrollera att du har:

  • .NET 8.0 eller senare
  • Microsoft Entra appregistrering med klientautentiseringsuppgifter (klienthemlighet eller certifikat)
  • För agentscenarier: Agentidentiteter som konfigurerats i din Microsoft Entra klientorganisation

Installera paket

Lägg till nödvändiga NuGet-paket i projektet:

dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Extensions.Hosting

Välj en konfigurationsmetod

Microsoft. Identity.Web innehåller två sätt att konfigurera daemonprogram:

Bäst för: Snabbprototyper, konsolappar, testning och enkla daemontjänster.

Följande kod skapar en TokenAcquirerFactory, konfigurerar underordnade API:er och Microsoft Graph och anropar 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();

fördelar:

  • Minimal mallkod
  • Laddas automatiskt appsettings.json
  • Perfekt för enkla scenarier
  • Enradsinitiering

Nackdelar:

  • Inte lämplig för parallella tester (singleton)

Bäst för: Produktionsprogram, komplexa scenarier, beroendeinmatning, testbarhet.

Följande kod använder den .NET Generisk värd för att konfigurera autentisering, tokenhämtning, cachelagring och en bakgrundstjänst.

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();

fördelar:

  • Fullständig kontroll över konfigurationsprovidrar
  • Bättre testbarhet med konstruktionsinjektion
  • Integrerar med ASP.NET Core värdmodell
  • Stödjer komplexa scenarier (flera autentiseringsscheman)
  • Produktionsklar arkitektur
  • Stödjer parallell körning av test (isolerad tjänsteleverantör per test)

Anmärkning

Parametern true i AddTokenAcquisition(true) innebär att tjänsten är registrerad som en singleton (enskild instans för appens livslängd). Använd false för begränsad livslängd i webbprogram.

Rekommendation: Börja med TokenAcquirerFactory för prototyper och enkelt-trådade tester. Migrera till det fullständiga ServiceCollection mönstret när du skapar produktionsprogram eller kör parallella tester.


Konfigurera standard daemonprogram

Standard daemonprogram autentiserar med klientautentiseringsuppgifter (klienthemlighet eller certifikat) och hämtar åtkomsttoken endast för appar för att anropa API:er.

Konfigurera autentiseringsinställningar

Lägg till följande konfiguration i appsettings.json-filen . Du kan använda antingen en klienthemlighet eller ett certifikat (rekommenderas för produktion):

{
  "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
    ]
  }
}

Viktigt: Ange att du appsettings.json vill kopiera till utdatakatalogen. Lägg till följande i .csproj filen:

<ItemGroup>
  <None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

ASP.NET Core program kopierar den här filen automatiskt, men daemon-appar (och OWIN-appar) gör det inte.

Konfigurera tjänstkonfiguration

Följande Program.cs kod registrerar Microsoft identitetsalternativ, tokenförvärv, cachelagring och en värdbaserad bakgrundstjänst:

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();

Anropa Microsoft Graph

Följande DaemonWorker.cs-klass använder Graph SDK för att lista användare enligt ett återkommande schema:

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);
        }
    }
}

Använd IAuthorizationHeaderProvider

Om du vill ha mer kontroll över HTTP-anrop använder du IAuthorizationHeaderProvider för att skapa auktoriseringshuvuden manuellt:

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;
    }
}

Se även Calling downstream API:er för att lära dig mer om alla sätt Microsoft Identity Web föreslår att anropa underordnade API:er.


Konfigurera autonoma agenter (agentidentitet)

Autonoma agenter använder agentidentiteter för att hämta endast apptoken. Det här mönstret är användbart för Copilot scenarier och autonoma tjänster.

Anmärkning

Microsoft rekommenderar att agenter som anropar underordnade API:er gör det från skyddade webb-API:er, även när agenterna hämtar en apptoken.

Konfigurera agenttjänster

Följande kod konfigurerar stöd för autentisering, tokenförvärv och agentidentitet med hjälp av minnesintern konfiguration:

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();

Hämta token med agentidentitet

När du har konfigurerat agenttjänster hämtar du tokens med antingen IAuthorizationHeaderProvider eller 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);
    });
});

Granska ett fullständigt exempel på en autonom agent

Följande klass omsluter anskaffning av agentidentitetstoken och Graph API anrop till en återanvändbar tjänst:

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>();
    }
}

Konfigurera agentens användaridentitet

Agentanvändarens identitet gör det möjligt för agenter att agera för en agentanvändare med delegerade behörigheter. Använd det här mönstret för agenter som behöver en egen postlåda eller andra resurser med användaromfattning.

Förutsättningar

Om du vill använda agentens användaridentitet behöver du:

  • Agentritning registrerad i Microsoft Entra ID
  • Agentidentitet skapad och länkad till agentprogrammet
  • Agentanvändaridentitet som är associerad med agentidentiteten

Konfigurera agentanvändartjänster

Följande kod konfigurerar agentprogrammets identitet med en certifikatautentiseringsuppgift och registrerar de tjänster som krävs:

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();

Hämta användartoken med agentidentitet

Du kan identifiera målanvändaren via UPN eller objekt-ID.

Efter användarnamn (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));
});

Efter användarobjekt-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));
});

Cachetoken med ClaimsPrincipal

För bättre prestanda cachelagrar du användartoken genom att skicka en ClaimsPrincipal instans. Det första anropet fyller huvudprincipalen med uid och utid claims. Efterföljande anrop återanvänder den cachelagrade token.

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

Åsidosätt hyresgästen

För scenarier med flera klientorganisationer kan du åsidosätta klientorganisationen vid körning. Detta är användbart när appen är konfigurerad med "common" men behöver rikta in sig på en specifik klientorganisation:

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";
    });
});

Granska ett exempel på en fullständig agentanvändares identitet

Följande klass innehåller metoder för att hämta användarprofiler och auktoriseringshuvuden med hjälp av agentens användaridentitet:

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());
    }
}

Skapa återanvändbar tjänstkonfiguration

Definiera en tilläggsmetod

Skapa en återanvändbar tilläggsmetod för att kapsla in agentidentitetskonfigurationen i ditt program:

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();
    }
}

Använd tilläggsmetoden

Anropa tilläggsmetoden för att konfigurera tjänster på en enda rad:

var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

var serviceProvider = services.ConfigureServicesForAgentIdentities(configuration);

Anropa API:er

Det här avsnittet visar hur du anropar API:er med var och en av de tre autentiseringsmönstren.

Anropa Microsoft Graph

Följande exempel visar att anropa Microsoft Graph som en standard daemon, en autonom agent och en agentanvändares identitet:

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"));
});

Anropa anpassade API:er med IDownstreamApi

Använd IDownstreamApi för att anropa dina egna skyddade API:er med något av de tre autentiseringsmönstren:

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");
    });

Gör manuella HTTP-anrop

Använd IAuthorizationHeaderProvider direkt när du behöver fullständig kontroll över HTTP-begäranden:

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);

Konfigurera cachelagring av token

Välj en cachelagringsstrategi baserat på din miljö.

Utveckling: Minnesintern cache

Använd minnesintern cachelagring för lokal utveckling och testning:

services.AddInMemoryTokenCaches();

Produktion: Distribuerad cache

För produktion använder du en distribuerad cache för att spara tokens över appomstarter och skalningsutökade instanser.

SQL Server

Lagra token i en SQL Server tabell:

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = configuration["ConnectionStrings:TokenCache"];
    options.SchemaName = "dbo";
    options.TableName = "TokenCache";
});
services.AddDistributedTokenCaches();

Redis

Använd Redis för cachelagring av distribuerade token med höga prestanda:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = configuration["Redis:ConnectionString"];
    options.InstanceName = "TokenCache_";
});
services.AddDistributedTokenCaches();

Cosmos DB

Använd Cosmos DB för globalt distribuerad tokencachelagring:

services.AddCosmosDbTokenCaches(options =>
{
    options.CosmosDbConnectionString = configuration["CosmosDb:ConnectionString"];
    options.DatabaseId = "TokenCache";
    options.ContainerId = "Tokens";
});

Läs mer:Konfiguration av tokencache


Utforska Azure exempel

Microsoft innehåller exempel som visar daemonappmönster.

Exempellagringsplats

active-directory-dotnetcore-daemon-v2

Den här lagringsplatsen innehåller flera scenarier:

Exempel Beskrivning Link
1-Call-MSGraph Grundläggande daemonanrop Microsoft Graph med klientautentiseringsuppgifter Visa Exempel
2-Call-OwnApi Daemon anropar ditt eget skyddade webb-API Visa Exempel
3-Using-KeyVault Daemon med Azure Key Vault för certifikatlagring Visa Exempel
4-Multi-Tenant Daemonprogram för flera hyresgäster Visa Exempel
5-Call-MSGraph-ManagedIdentity Daemon med hanterad identitet på Azure Visa Exempel

Jämföra exempelmönster med produktionsmönster

De Azure exemplen använder TokenAcquirerFactory.GetDefaultInstance() för enkelhetens skull – den rekommenderade metoden för simple-konsolappar, prototyper och tester. Den här guiden visar båda mönstren:

TokenAcquirerFactory Pattern (Azure Samples):

// Simple, perfect for prototypes and tests
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi("MyApi", ...);
var serviceProvider = tokenAcquirerFactory.Build();

Fullständigt ServiceCollection-mönster (produktionsprogram):

// More control, testable, follows DI best practices
var services = new ServiceCollection();
services.AddTokenAcquisition(true); // true = singleton
services.Configure<MicrosoftIdentityApplicationOptions>(...);
var serviceProvider = services.BuildServiceProvider();

När du ska använda vad:

  • Använda TokenAcquirerFactory för: Konsolappar, snabbprototyper, enhetstester, enkla daemontjänster
  • Använd ServiceCollection för: Produktionsprogram, ASP.NET Core integrering, komplexa DI-scenarier, bakgrundstjänster med IHostedService

Båda metoderna stöds fullt ut och är produktionsklara. Välj baserat på programmets komplexitets- och integrationsbehov.


Felsök vanliga fel

AADSTS700016: Programmet hittades inte

Orsak: Ogiltigt ClientId eller program som inte har registrerats i klientorganisationen.

Solution: Kontrollera att ClientId i konfigurationen matchar din Microsoft Entra appregistrering.

AADSTS7000215: Ogiltig klienthemlighet

Orsaka: Klienthemligheten är felaktig, har upphört att gälla eller inte konfigurerats.

Lösning:

  • Kontrollera att hemligheten i Azure portalen matchar din konfiguration
  • Kontrollera sekretessens utgångsdatum
  • Överväg att använda certifikat för produktion

AADSTS700027: Klientpåståendet innehåller en ogiltig signatur

Orsaka: Certifikatet hittades inte, har upphört att gälla eller den privata nyckeln är inte tillgänglig.

Lösning:

  • Kontrollera att certifikatet har installerats i rätt certifikatarkiv
  • Kontrollera att certifikatets unika namn matchar konfigurationen
  • Kontrollera att programmet har behörighet att läsa privat nyckel
  • Se Konfigurationsguide för certifikat

AADSTS650052: Appen behöver åtkomst till en tjänst

Orsaka: Nödvändiga API-behörigheter som inte beviljats eller administratörsmedgivande saknas.

Lösning:

  1. Gå till Azure portalen → App registrations → Din app → API-behörigheter
  2. Lägg till nödvändiga behörigheter (t.ex. User.Read.All för Microsoft Graph)
  3. Klicka på knappen Bevilja administratörsmedgivande

Agentidentitetsfel

AADSTS50105: Den inloggade användaren har inte tilldelats en roll

Orsaka: Agentidentiteten är inte korrekt konfigurerad eller inte tilldelad till programmet.

Lösning:

  • Kontrollera att agentidentiteten finns i Microsoft Entra ID
  • Kontrollera att agentidentiteten är länkad till ditt program
  • Kontrollera att agentidentiteten har nödvändiga behörigheter

Token som har hämtats men med fel behörighet

Orsaka: Använda agentens användaridentitet men begära appbehörigheter, eller vice versa.

Lösning:

  • För endast apptoken: Använd CreateAuthorizationHeaderForAppAsync med WithAgentIdentity
  • För delegerade token: Använd CreateAuthorizationHeaderForUserAsync med WithAgentUserIdentity
  • Se till att API-behörigheter matchar tokentyp (program jämfört med delegerad)

Problem med token-cachelagring

Problem: Tokens cachas inte, vilket tvingar fram en ny anskaffning varje gång.

Lösning:

  • För agentanvändarens identitet: Återanvänd samma ClaimsPrincipal instans mellan anrop
  • Verifiera distribuerad cacheanslutning (om du använder Redis/SQL)
  • Aktivera felsökningsloggning för att se cacheåtgärder

Detaljerad diagnostik:Guide för loggning och diagnostik