Intégration de l’API d’aval avec Microsoft.Identity.Web

Microsoft. Identity.Web fournit plusieurs approches pour appeler des API en aval, notamment des Microsoft Graph, des services Azure et des API REST personnalisées, à partir de vos applications ASP.NET Core, OWIN ou .NET. Cet article vous aide à choisir l’approche appropriée pour votre scénario et à commencer rapidement.

Sélection de l’approche

Utilisez cet arbre de décision pour sélectionner la meilleure méthode pour votre scénario :

Type d’API / Scénario Décision / Critères Client/classe recommandé
Microsoft Graph Vous devez appeler des APIs Microsoft Graph GraphServiceClient
Kit de développement logiciel (SDK) Azure (stockage, coffre de clés, etc.) Vous devez appeler des API Azure (Kit de développement logiciel (SDK) Azure) MicrosoftIdentityTokenCredential avec des clients Kit de développement logiciel (SDK) Azure
API personnalisée avec liaison de jeton Sécurité renforcée avec l'association de certificat (mTLS PoP) IDownstreamApi avec ProtocolScheme: "MTLS_POP"
API personnalisée avec liaison de jeton Sécurité renforcée avec l’intégration de HttpClient (mTLS PoP) MicrosoftIdentityMessageHandler avec ProtocolScheme: "MTLS_POP"
API personnalisée Simple, configurable IDownstreamApi
API personnalisée utilisation de HttpClient + délégation du gestionnaire MicrosoftIdentityMessageHandler
API personnalisée utilisation de votre HttpClient IAuthorizationHeaderProvider

Comparaison d’approches par complexité et flexibilité

Le tableau suivant résume chaque approche par son cas d’usage, son niveau de complexité et sa flexibilité prévus.

Approche Idéal pour Complexité Paramétrage Flexibilité
GraphServiceClient API Microsoft Graph Low Simplicité Moyenne
MicrosoftIdentityTokenCredential Clients du SDK Azure Low Simplicité Low
IDownstreamApi API REST avec des modèles standard Low JSON + Code Moyenne
MicrosoftIdentityMessageHandler HttpClient avec pipeline d’authentification Moyenne Code Élevé
IAuthorizationHeaderProvider Logique d’authentification personnalisée Élevé Code Très élevé

Modèles d’acquisition de jetons

Microsoft. Identity.Web prend en charge trois modèles d’acquisition de jetons principaux :

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

Autorisations déléguées (jetons utilisateur)

Utilisez des autorisations déléguées lorsque votre application agit pour le compte d’un utilisateur connecté.

  • Scénario : l’application web appelle l’API pour le compte de l’utilisateur connecté et de l’identité utilisateur de l’agent autonome.
  • Type de jeton : jeton d’accès avec des autorisations déléguées
  • Méthodes : CreateAuthorizationHeaderForUserAsync(), GetForUserAsync()

Autorisations d’application (jetons d’application uniquement)

Utilisez les autorisations d’application lorsqu’aucun utilisateur n’est présent et que l’application s’authentifie comme elle-même.

  • Scénario : Une application démon ou un service en arrière-plan appelle l'API. Identité d’agent autonome
  • Type de jeton : jeton d’accès avec autorisations d’application
  • Méthodes : CreateAuthorizationHeaderForAppAsync(), GetForAppAsync()

Flux "On-Behalf-Of" (OBO)

Utilisez le flux OBO lorsqu’une API web doit appeler une autre API en aval tout en préservant l’identité de l’utilisateur.

  • Scénario : l’API web reçoit le jeton utilisateur, appelle une autre API pour le compte de cet utilisateur et de ces agents interactifs.
  • Type de jeton : Nouveau jeton d’accès via le flux OBO
  • Méthodes : CreateAuthorizationHeaderForUserAsync() à partir du contexte d’API web

Liaison de jeton (mTLS PoP)

La liaison de jeton ajoute une couche de sécurité supplémentaire en liant par chiffrement des jetons d’accès aux certificats X.509.

  • Scénario : sécurité renforcée où les jetons sont liés par chiffrement aux certificats conformément à la norme RFC 8705
  • Type de jeton : jeton d’accès avec liaison de certificat (cnf revendication)
  • Méthodes : GetForAppAsync() avec ProtocolScheme: "MTLS_POP"
  • Sécurité : empêche le vol de jetons en liant des jetons à des certificats spécifiques

En savoir plus sur la liaison de jeton avec mTLS PoP

Exemples de code de démarrage rapide

Les exemples suivants illustrent chaque approche avec du code de bout en bout que vous pouvez adapter à votre application.

L’exemple suivant inscrit GraphServiceClient et l’utilise pour appeler Microsoft Graph au nom de l’utilisateur connecté et en tant qu’appel d’application uniquement.

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

En savoir plus sur l’intégration Microsoft Graph

Migration de GraphServiceClient et utilisation détaillée

L’exemple suivant inscrit MicrosoftIdentityTokenCredential et le transmet à un client Stockage Blob 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;
    }
}

En savoir plus sur l’intégration Kit de développement logiciel (SDK) Azure

L’exemple suivant configure une API en aval nommée dans appsettings.json et l’appelle avec des jetons délégués et des jetons d'application uniquement.

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

En savoir plus sur IDownstreamApi

Liaison de jeton avec mTLS PoP (sécurité renforcée)

La liaison de jetons offre une sécurité renforcée en liant les jetons d’accès par chiffrement aux certificats X.509. Même si un jeton est intercepté, il ne peut pas être utilisé sans le certificat correspondant.

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

Principaux avantages :

  • Protection contre le vol de jetons : les jetons volés sont inutiles sans le certificat
  • Prévention des attaques par relecture : les jetons ne peuvent pas être relus à partir de différents clients
  • Alignement de confiance zéro : liaison de chiffrement forte entre le client et le jeton

En savoir plus sur la liaison de jetons (mTLS PoP)

MicrosoftIdentityMessageHandler (pour l’intégration de HttpClient)

L’exemple suivant ajoute un gestionnaire de délégation à un HttpClient afin que chaque demande sortante inclut automatiquement un en-tête d’autorisation. Le gestionnaire inscrit des étendues au démarrage, et les demandes individuelles peuvent remplacer les options de jeton.

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

En savoir plus sur MicrosoftIdentityMessageHandler

IAuthorizationHeaderProvider (flexibilité maximale)

L’exemple suivant récupère directement un en-tête d’autorisation afin de pouvoir l’attacher à n’importe quelle requête HTTP en même temps que les en-têtes personnalisés.

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

En savoir plus sur IAuthorizationHeaderProvider

Modèles de configuration

Microsoft. Identity.Web prend en charge la configuration JSON et la configuration basée sur le code.

configuration de appsettings.json

Le code JSON suivant montre une configuration classique qui enregistre les informations d’identification Microsoft Entra ID et deux APIs postérieures.

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

Pour les applications démon/console, définissez appsettings.json les propriétés : « Copier dans le répertoire de sortie » = « Copier si plus récent »

En savoir plus sur la configuration des informations d’identification

Configuration basée sur le code

Vous pouvez également configurer des informations d’identification et des API en aval entièrement dans le code, comme l’illustre l’exemple suivant.

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

Guides spécifiques au scénario

La meilleure approche dépend de l’emplacement à partir duquel vous appelez l’API :

Intégration d’applications web

Les applications web appellent généralement des API en aval pour le compte de l’utilisateur connecté.

  • Modèle principal : Autorisations déléguées (au nom de l’utilisateur)
  • Acquisition de jeton : Se produit automatiquement lors de la connexion
  • Considérations spéciales : Consentement incrémentiel, gestion des échecs de consentement

Lire le guide Web Apps

Intégration de l’API web

Les API web utilisent le flux « On-Behalf-Of » pour échanger un jeton utilisateur entrant contre un nouveau jeton destiné à l'API en aval.

  • Modèle principal : flux OBO (On-Behalf-Of)
  • Acquisition de jeton : Échangez le jeton entrant contre le jeton en aval
  • Considérations spéciales : processus longs, mise en cache des jetons, identités d’agent.

Lire le guide des API web

Intégration de l’application démon

Les applications démon s’authentifient comme elles-mêmes sans utilisateur connecté.

  • Modèle principal : Autorisations d’application (application uniquement)
  • Acquisition de jeton : flux d’informations d’identification du client
  • Considérations particulières : Aucun contexte utilisateur n’exige le consentement de l’administrateur
  • Avancé : agents autonomes, identités utilisateur d’agent

Lisez le guide des applications démon

Gestion des erreurs pour l’acquisition de jetons

Toutes les méthodes d’acquisition de jetons peuvent lever des exceptions que votre application doit gérer. Dans les applications web, l’attribut gère le [AuthorizeForScope(scopes)] consentement incrémentiel de l’utilisateur ou la nouvelle signature.

L’exemple suivant montre comment intercepter et gérer les exceptions courantes d’acquisition de jetons.

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

Scénarios d’erreur courants

Le tableau suivant répertorie les exceptions les plus courantes et comment les résoudre.

Exception Meaning Solution
MicrosoftIdentityWebChallengeUserException Consentement de l’utilisateur requis Redirigez vers Microsoft Entra ID pour obtenir le consentement. Utiliser l’attribut AuthorizeForScopes ou la classe ConsentHandler
MsalUiRequiredException Authentification interactive nécessaire Gérer les défis dans les applications web
MsalServiceException erreur de service Microsoft Entra ID Vérifier la configuration, réessayer
HttpRequestException Erreur d’API en aval Gérer les erreurs spécifiques à l’API

Packages NuGet exigés

Choisissez le package qui correspond à votre scénario. Le tableau suivant répertorie chaque package et quand l’utiliser.

Package Objectif Quand utiliser
Microsoft. Identity.Web.TokenAcquisition Services d’acquisition de jetons Package principal
Microsoft. Identity.Web.DownstreamApi Abstraction IDownstreamApi Appel d’API REST
Microsoft. Identity.Web.GraphServiceClient intégration de Microsoft Graph Microsoft Graph (guide de migration) - Appel
Microsoft. Identity.Web. Azure intégration de Kit de développement logiciel (SDK) Azure Appel de services Azure
Microsoft. Identity.Web applications web et API web ASP.NET Core ASP.NET Core
Microsoft. Identity.Web.OWIN Applications web et API web ASP.NET OWIN OWIN

Explorez ces guides pour obtenir des procédures pas à pas détaillées et des scénarios avancés.