Integrazione dell'API downstream con Microsoft. Identity.Web

Microsoft. Identity.Web offre più approcci per chiamare le API downstream, tra cui Microsoft Graph, servizi Azure e API REST personalizzate, dalle applicazioni ASP.NET Core, OWIN o .NET. Questo articolo illustra come scegliere l'approccio appropriato per lo scenario e iniziare rapidamente.

Selezione dell'approccio

Usare questo albero delle decisioni per selezionare il metodo migliore per lo scenario:

Tipo di API/Scenario Decisione/Criteri Client/Classe Consigliato
Microsoft Graph È necessario chiamare le API di Microsoft Graph GraphServiceClient
Azure SDK (Archiviazione, KeyVault e così via) È necessario chiamare le API Azure (Azure SDK) MicrosoftIdentityTokenCredential con i client dell'SDK di Azure
API personalizzata con associazione di token Sicurezza avanzata con l'associazione di certificati (mTLS PoP) IDownstreamApi con ProtocolScheme: "MTLS_POP"
API personalizzata con associazione di token Sicurezza avanzata con l'integrazione di HttpClient (mTLS PoP) MicrosoftIdentityMessageHandler con ProtocolScheme: "MTLS_POP"
API personalizzata Semplice, configurabile IDownstreamApi
API personalizzata utilizzando HttpClient + handler delegato MicrosoftIdentityMessageHandler
API personalizzata utilizzando il tuo HttpClient IAuthorizationHeaderProvider

Confronto degli approcci in base alla complessità e alla flessibilità

La tabella seguente riepiloga ogni approccio in base al caso d'uso previsto, al livello di complessità e alla flessibilità.

Avvicinarsi Ideale per Complessità Configurazione Flessibilità
GraphServiceClient API di Microsoft Graph Low Semplice Medium
MicrosoftIdentityTokenCredential i client dell'SDK di Azure Low Semplice Low
IDownstreamApi API REST con modelli standard Low JSON + Codice Medium
MicrosoftIdentityMessageHandler HttpClient con pipeline di autenticazione Medium Codice Alto
IAuthorizationHeaderProvider Logica di autenticazione personalizzata Alto Codice Molto alto

Modelli di acquisizione dei token

Microsoft. Identity.Web supporta tre modelli principali di acquisizione dei token:

graph LR
    A[Token Acquisition] --> B[Delegated<br/>On behalf of user]
    A --> C[App-Only<br/>Application permissions in all apps]
    A --> D[On-Behalf-Of OBO<br/>in web API]

    B --> B1[Web Apps]
    B --> B2[Daemon acting as user / user agent]
    C --> C1[Daemon Apps]
    C --> C2[Web APIs with app permissions]
    D --> D1[Web APIs calling other APIs]

    style B fill:#cfe2ff
    style C fill:#fff3cd
    style D fill:#f8d7da

Autorizzazioni delegate (token utente)

Usare le autorizzazioni delegate quando l'applicazione agisce per conto di un utente connesso.

  • Scenario: l'app Web chiama l'API per conto dell'utente connesso e dell'identità utente dell'agente autonomo.
  • Tipo di token: token di accesso con autorizzazioni delegate
  • Metodi: CreateAuthorizationHeaderForUserAsync(), GetForUserAsync()

Autorizzazioni dell'applicazione (token solo dell'app)

Usare le autorizzazioni dell'applicazione quando non è presente alcun utente e l'app esegue l'autenticazione come se stessa.

  • Scenario: L'app daemon o il servizio in background esegue chiamate API. Identità dell'agente autonomo
  • Tipo di token: token di accesso con autorizzazioni dell'applicazione
  • Metodi: CreateAuthorizationHeaderForAppAsync(), GetForAppAsync()

Flusso per Conto di terzi (OBO)

Usare il flusso OBO quando un'API Web deve chiamare un'altra API downstream mantenendo al tempo stesso l'identità dell'utente.

  • Scenario: l'API Web riceve il token utente, chiama un'altra API per conto dell'utente e degli agenti interattivi.
  • Tipo di token: nuovo token di accesso tramite il flusso OBO
  • Metodi: CreateAuthorizationHeaderForUserAsync() dal contesto dell'API Web

Associazione di token (mTLS PoP)

L'associazione di token aggiunge un ulteriore livello di sicurezza associando crittograficamente i token di accesso ai certificati X.509.

  • Scenario: sicurezza avanzata in cui i token sono associati in modo crittografico ai certificati in base a RFC 8705
  • Tipo di token: token di accesso con associazione ai certificati (cnf dichiarazione)
  • Metodi: GetForAppAsync() con ProtocolScheme: "MTLS_POP"
  • Sicurezza: impedisce il furto di token associando token a certificati specifici

Altre informazioni sull'associazione di token con mTLS PoP

Esempi di codice di avvio rapido

Gli esempi seguenti illustrano ogni approccio con codice end-to-end che è possibile adattare all'applicazione.

L'esempio seguente registra GraphServiceClient e lo usa per chiamare Microsoft Graph per conto dell'utente connesso e come chiamata esclusiva dell'app.

// Installation
// dotnet add package Microsoft.Identity.Web.GraphServiceClient

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddMicrosoftGraph();

// Usage in controller
public class HomeController : Controller
{
    private readonly GraphServiceClient _graphClient;

    public HomeController(GraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<IActionResult> Profile()
    {
        // Delegated - calls on behalf of signed-in user
        var user = await _graphClient.Me.GetAsync();

        // App-only - requires app permissions
        var users = await _graphClient.Users
            .GetAsync(r => r.Options.WithAppOnly());

        return View(user);
    }
}

Altre informazioni sull'integrazione Microsoft Graph

Migrazione graphServiceClient e utilizzo dettagliato

L'esempio seguente registra MicrosoftIdentityTokenCredential e lo passa a un client Archiviazione BLOB di Azure.

// Installation
// dotnet add package Microsoft.Identity.Web.Azure
// dotnet add package Azure.Storage.Blobs

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddMicrosoftIdentityAzureTokenCredential();

// Usage
public class StorageService
{
    private readonly MicrosoftIdentityTokenCredential _credential;

    public StorageService(MicrosoftIdentityTokenCredential credential)
    {
        _credential = credential;
    }

    public async Task<List<string>> ListBlobsAsync()
    {
        var blobClient = new BlobServiceClient(
            new Uri("https://myaccount.blob.core.windows.net"),
            _credential);

        var container = blobClient.GetBlobContainerClient("mycontainer");
        var blobs = new List<string>();

        await foreach (var blob in container.GetBlobsAsync())
        {
            blobs.Add(blob.Name);
        }

        return blobs;
    }
}

Altre informazioni sull'integrazione Azure SDK

L'esempio seguente configura un'API downstream denominata in appsettings.json e la chiama con token sia delegati che solo app.

// Installation
// dotnet add package Microsoft.Identity.Web.DownstreamApi

// appsettings.json
{
  "DownstreamApis": {
    "MyApi": {
      "BaseUrl": "https://myapi.example.com",
      "Scopes": ["api://myapi/read", "api://myapi/write"]
    }
  }
}

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddDownstreamApis(
    builder.Configuration.GetSection("DownstreamApis"));

// Usage
public class ApiService
{
    private readonly IDownstreamApi _api;

    public ApiService(IDownstreamApi api)
    {
        _api = api;
    }

    public async Task<Product> GetProductAsync(int id)
    {
        // Delegated - on behalf of user
        return await _api.GetForUserAsync<Product>(
            "MyApi",
            $"api/products/{id}"
        );
    }

    public async Task<List<Product>> GetAllProductsAsync()
    {
        // App-only - using app permissions
        return await _api.GetForAppAsync<List<Product>>(
            "MyApi",
            "api/products");
    }
}

Altre informazioni su IDownstreamApi

Associazione di token con mTLS PoP (sicurezza avanzata)

L'associazione di token offre una maggiore sicurezza associando i token di accesso crittograficamente ai certificati X.509. Anche se un token viene intercettato, non può essere usato senza il certificato corrispondente.

// Installation
// dotnet add package Microsoft.Identity.Web.DownstreamApi

// appsettings.json
{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "StoreWithDistinguishedName",
        "CertificateStorePath": "CurrentUser/My",
        "CertificateDistinguishedName": "CN=YourCertificate"
      }
    ],
    "SendX5c": true
  },
  "SecureApi": {
    "BaseUrl": "https://api.contoso.com/",
    "RelativePath": "api/data",
    "ProtocolScheme": "MTLS_POP",
    "RequestAppToken": true,
    "Scopes": [ "api://your-api/.default" ]
  }
}

// Startup configuration
builder.Services.AddDownstreamApi(
    "SecureApi",
    builder.Configuration.GetSection("SecureApi"));

// Usage
public class SecureApiService
{
    private readonly IDownstreamApi _api;

    public SecureApiService(IDownstreamApi api)
    {
        _api = api;
    }

    public async Task<SecureData> GetSecureDataAsync()
    {
        // Token is bound to certificate - enhanced security
        return await _api.GetForAppAsync<SecureData>("SecureApi");
    }
}

Vantaggi principali:

  • Protezione dal furto di token: i token rubati sono inutili senza il certificato
  • Prevenzione degli attacchi di riproduzione: i token non possono essere riprodotti da client diversi
  • Allineamento zero trust: associazione crittografica avanzata tra il client e il token

Altre informazioni sull'associazione di token (poP mTLS)

MicrosoftIdentityMessageHandler (per l'integrazione di HttpClient)

Nell'esempio seguente viene aggiunto un gestore di delega a un oggetto HttpClient in modo che ogni richiesta in uscita includa automaticamente un'intestazione di autorizzazione. Il gestore registra gli ambiti all'avvio del sistema e le singole richieste possono eseguire l'override delle opzioni del token.

// Startup configuration
using Microsoft.Identity.Web;

builder.Services.AddHttpClient("MyApiClient", client =>
{
    client.BaseAddress = new Uri("https://myapi.example.com");
})
.AddHttpMessageHandler(sp => new MicrosoftIdentityMessageHandler(
    sp.GetRequiredService<IAuthorizationHeaderProvider>(),
    new MicrosoftIdentityMessageHandlerOptions
    {
        Scopes = new[] { "api://myapi/.default" }
    }));

// Usage
public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("MyApiClient");
    }

    public async Task<Product> GetProductAsync(int id)
    {
        var request = new HttpRequestMessage(HttpMethod.Get, $"api/products/{id}")
            .WithAuthenticationOptions(options =>
            {
                options.RequestAppToken = false; // Use delegated token
                options.scopes = [ "myApi.scopes" ];
            });

        var response = await _httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<Product>();
    }
}

Altre informazioni su MicrosoftIdentityMessageHandler

IAuthorizationHeaderProvider (massima flessibilità)

Nell'esempio seguente viene recuperata direttamente un'intestazione di autorizzazione in modo da poterla collegare a qualsiasi richiesta HTTP insieme a intestazioni personalizzate.

// Direct usage for custom scenarios
public class CustomAuthService
{
    private readonly IAuthorizationHeaderProvider _headerProvider;

    public CustomAuthService(IAuthorizationHeaderProvider headerProvider)
    {
        _headerProvider = headerProvider;
    }

    public async Task<string> CallApiAsync()
    {
        // Get auth header (includes "Bearer " + token)
        string authHeader = await _headerProvider
            .CreateAuthorizationHeaderForUserAsync(
                scopes: new[] { "api://myapi/.default" });

        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("Authorization", authHeader);
        client.DefaultRequestHeaders.Add("X-Custom-Header", "MyValue");

        var response = await client.GetStringAsync("https://myapi.example.com/data");
        return response;
    }
}

Altre informazioni su IAuthorizationHeaderProvider

Modelli di configurazione

Microsoft. Identity.Web supporta sia la configurazione JSON che la configurazione basata su codice.

configurazione di appsettings.json

Il codice JSON seguente illustra una configurazione tipica che registra le credenziali Microsoft Entra ID e due API downstream.

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity"
      }
    ]
  },
  "DownstreamApis": {
    "MicrosoftGraph": {
      "BaseUrl": "https://graph.microsoft.com/v1.0",
      "Scopes": ["User.Read", "Mail.Read"]
    },
    "MyApi": {
      "BaseUrl": "https://myapi.example.com",
      "Scopes": ["api://myapi/read"]
    }
  }
}

Note

Per le app daemon/console, impostare appsettings.json le proprietà: "Copia nella directory di output" = "Copia se più recente"

Altre informazioni sulla configurazione delle credenziali

Configurazione basata su codice

È anche possibile configurare le credenziali e le API downstream interamente nel codice, come illustrato nell'esempio seguente.

// Explicit configuration in code
builder.Services.Configure<MicrosoftIdentityApplicationOptions>(options =>
{
    options.Instance = "https://login.microsoftonline.com/";
    options.TenantId = "your-tenant-id";
    options.ClientId = "your-client-id";
    options.ClientCredentials = new[]
    {
        CertificateDescription.FromKeyVault(
            "https://myvault.vault.azure.net",
            "MyCertificate")
    };
});

builder.Services.AddDownstreamApi("MyApi", options =>
{
    options.BaseUrl = "https://myapi.example.com";
    options.Scopes = new[] { "api://myapi/read" };
});

Guide specifiche dello scenario

L'approccio migliore dipende dalla posizione da cui si chiama l'API:

Integrazione di app Web

Le app Web chiamano in genere API downstream per conto dell'utente connesso.

  • Modello primario: autorizzazioni delegate (per conto dell'utente)
  • Acquisizione di token: si verifica automaticamente durante l'accesso
  • Considerazioni speciali: consenso incrementale, gestione degli errori di consenso

Leggere la guida App Web

Integrazione dell'API Web

Le API Web usano il flusso on-Behalf-Of per scambiare un token utente in ingresso per un nuovo token con ambito all'API downstream.

  • Modello primario: flusso "On-Behalf-Of" (OBO)
  • Acquisizione Token: Scambio del token in ingresso con il token downstream
  • Considerazioni speciali: processi a esecuzione prolungata, memorizzazione nella cache dei token, identità dell'agente.

Leggere la guida alle API Web

Integrazione dell'applicazione daemon

Le app daemon eseguono l'autenticazione come se stesse senza un utente connesso.

  • Modello primario: autorizzazioni dell'applicazione (solo app)
  • Acquisizione di token: flusso di credenziali client
  • Considerazioni speciali: nessun contesto utente, richiede il consenso dell'amministratore
  • Avanzate: agenti autonomi, identità utente agente

Leggere la guida alle applicazioni daemon

Gestione degli errori per l'acquisizione di token

Tutti i metodi di acquisizione di token possono generare eccezioni che l'applicazione deve gestire. Nelle app Web l'attributo gestisce il [AuthorizeForScope(scopes)] consenso incrementale dell'utente o la rifirmazione.

Nell'esempio seguente viene illustrato come intercettare e gestire eccezioni comuni di acquisizione di token.

using Microsoft.Identity.Abstractions;

try
{
    var result = await _api.GetForUserAsync<Data>("MyApi", "api/data");
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
    // User needs to sign in or consent to additional scopes
    // In web apps, this triggers a redirect to Microsoft Entra ID
    throw;
}
catch (HttpRequestException ex)
{
    // Downstream API returned error
    _logger.LogError(ex, "API call failed");
}

Scenari di errore comuni

Nella tabella seguente sono elencate le eccezioni più comuni e come risolverle.

Eccezione Meaning Soluzione
MicrosoftIdentityWebChallengeUserException Consenso utente obbligatorio Reindirizza a Microsoft Entra ID per il consenso. Usare l'attributo AuthorizeForScopes o la classe ConsentHandler
MsalUiRequiredException Autenticazione interattiva necessaria Gestire nelle app Web con problemi
MsalServiceException errore del servizio Microsoft Entra ID Controllare la configurazione, riprovare
HttpRequestException Errore dell'API downstream Gestire errori specifici dell'API

Pacchetti NuGet necessari

Scegliere il pacchetto corrispondente allo scenario. La tabella seguente elenca ogni pacchetto e quando usarlo.

Package Scopo Quando utilizzare
Microsoft. Identity.Web.TokenAcquisition Servizi di acquisizione dei token Pacchetto principale
Microsoft. Identity.Web.DownstreamApi Astrazione IDownstreamApi Chiamate delle API REST
Microsoft. Identity.Web.GraphServiceClient integrazione di Microsoft Graph Chiamata di Microsoft Graph (guida migrazione)
Microsoft. Identity.Web. Azure integrazione di Azure SDK Chiamata di servizi Azure
Microsoft. Identity.Web applicazioni web e API web di ASP.NET Core ASP.NET Core
Microsoft. Identity.Web.OWIN ASP.NET app OWIN Web e API Web OWIN

Esplorare queste guide per procedure dettagliate e scenari avanzati.