Integração de API downstream com Microsoft.Identity.Web

Microsoft. O Identity.Web fornece várias abordagens para chamar APIs downstream, incluindo Microsoft Graph, serviços Azure e APIs REST personalizadas, de seus aplicativos ASP.NET Core, OWIN ou .NET. Este artigo ajuda você a escolher a abordagem certa para seu cenário e começar rapidamente.

Seleção de abordagem

Use esta árvore de decisão para selecionar o melhor método para seu cenário:

Tipo/cenário de API Decisão/Critérios Cliente/classe recomendado
Microsoft Graph Você precisa chamar as APIs do Microsoft Graph GraphServiceClient
SDK do Azure (Armazenamento, KeyVault, etc.) Você precisa chamar APIs de Azure (SDK do Azure) MicrosoftIdentityTokenCredential com os clientes do SDK do Azure
API personalizada com associação de token Segurança aprimorada com associação de certificado (mTLS PoP) IDownstreamApi com ProtocolScheme: "MTLS_POP"
API personalizada com associação de token Segurança aprimorada com integração httpClient (mTLS PoP) MicrosoftIdentityMessageHandler com ProtocolScheme: "MTLS_POP"
API Personalizada Simples, configurável IDownstreamApi
API Personalizada usando HttpClient + manipulador de delegação MicrosoftIdentityMessageHandler
API Personalizada usando o HttpClient IAuthorizationHeaderProvider

Comparação de abordagem por complexidade e flexibilidade

A tabela a seguir resume cada abordagem por seu caso de uso pretendido, nível de complexidade e flexibilidade.

Abordagem Melhor para Complexidade Configuração Flexibilidade
GraphServiceClient APIs de Microsoft Graph Baixo Simples Medium
MicrosoftIdentityTokenCredential clientes do SDK do Azure Baixo Simples Baixo
IDownstreamApi APIs REST com padrões padrão Baixo JSON + Código Medium
MicrosoftIdentityMessageHandler HttpClient com pipeline de autenticação Medium Code Alto
IAuthorizationHeaderProvider Lógica de autenticação personalizada Alto Code Muito alto

Padrões de aquisição de token

Microsoft. O Identity.Web dá suporte a três padrões principais de aquisição de 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

Permissões delegadas (tokens de usuário)

Use permissões delegadas quando seu aplicativo agir em nome de um usuário conectado.

  • Cenário: o aplicativo Web chama a API em nome do usuário conectado e da identidade do usuário do agente autônomo.
  • Tipo de token: token de acesso com permissões delegadas
  • Métodos: CreateAuthorizationHeaderForUserAsync(), GetForUserAsync()

Permissões de aplicativo (tokens somente de aplicativo)

Use permissões de aplicativo quando nenhum usuário estiver presente e o aplicativo se autenticar como ele mesmo.

  • Cenário: Aplicativo daemon ou serviço em segundo plano que faz chamadas de API. Identidade do agente autônomo
  • Tipo de token: token de acesso com permissões de aplicativo
  • Métodos: CreateAuthorizationHeaderForAppAsync(), GetForAppAsync()

O fluxo On-Behalf-Of (OBO)

Use o fluxo OBO quando uma API Web precisar chamar outra API downstream, preservando a identidade do usuário.

  • Cenário: a API Web recebe o token de usuário, chama outra API em nome desse usuário e agentes interativos.
  • Tipo de Token: Novo Token de Acesso via fluxo OBO
  • Métodos: CreateAuthorizationHeaderForUserAsync() no contexto da API Web

Associação de token (mTLS PoP)

A associação de token adiciona uma camada extra de segurança vinculando criptograficamente tokens de acesso a certificados X.509.

  • Cenário: segurança aprimorada em que os tokens são criptograficamente associados a certificados de acordo com RFC 8705
  • Tipo de token: token de acesso com associação de certificado (cnf claim)
  • Métodos: GetForAppAsync() com ProtocolScheme: "MTLS_POP"
  • Segurança: impede o roubo de tokens associando tokens a certificados específicos

Saiba mais sobre a associação de token com o mTLS PoP

Exemplos de código de início rápido

Os exemplos a seguir demonstram cada abordagem com código de ponta a ponta que você pode adaptar ao seu aplicativo.

O exemplo a seguir registra GraphServiceClient e o usa para chamar Microsoft Graph em nome do usuário conectado e como uma chamada somente de aplicativo.

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

Saiba mais sobre Microsoft Graph integração

Migração do GraphServiceClient e uso detalhado

O exemplo a seguir registra MicrosoftIdentityTokenCredential e o passa para um cliente Armazenamento de Blobs do 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;
    }
}

Saiba mais sobre SDK do Azure integração

O exemplo a seguir configura uma API downstream nomeada em appsettings.json e a chama usando tokens delegados e de aplicativo exclusivo.

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

Saiba mais sobre iDownstreamApi

Associação de token com mTLS PoP (segurança aprimorada)

A associação de token fornece segurança aprimorada vinculando tokens de acesso criptograficamente a certificados X.509. Mesmo se um token for interceptado, ele não poderá ser usado sem o certificado correspondente.

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

Principais benefícios:

  • Proteção contra roubo de token: tokens roubados são inúteis sem o certificado
  • Prevenção de ataque de reprodução: os tokens não podem ser reproduzidos de clientes diferentes
  • Alinhamento de confiança zero: associação criptográfica forte entre cliente e token

Saiba mais sobre a Associação de Token (mTLS PoP)

MicrosoftIdentityMessageHandler (para integração httpClient)

O exemplo a seguir adiciona um manipulador de delegação a um HttpClient para que cada solicitação de saída inclua automaticamente um cabeçalho de autorização. O manipulador registra escopos na inicialização e solicitações individuais podem substituir as opções de 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>();
    }
}

Saiba mais sobre MicrosoftIdentityMessageHandler

IAuthorizationHeaderProvider (flexibilidade máxima)

O exemplo a seguir recupera um cabeçalho de autorização diretamente para que você possa anexá-lo a qualquer solicitação HTTP junto com cabeçalhos personalizados.

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

Saiba mais sobre IAuthorizationHeaderProvider

Padrões de configuração

Microsoft. O Identity.Web dá suporte à configuração JSON e à configuração baseada em código.

configuração de appsettings.json

O JSON a seguir mostra uma configuração típica que registra credenciais do Microsoft Entra ID e duas APIs a jusante.

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

Para aplicativos daemon/console, defina as propriedades appsettings.json: "Copiar para o Diretório de Saída" = "Copiar se mais recente"

Saiba mais sobre a configuração de credenciais

Configuração baseada em código

Você também pode configurar credenciais e APIs downstream inteiramente no código, como mostra o exemplo a seguir.

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

Guias específicos de cenários

A melhor abordagem depende de onde você está chamando a API de:

Integração de aplicações Web

Os aplicativos Web normalmente chamam APIs downstream em nome do usuário conectado.

  • Padrão primário: permissões delegadas (em nome do usuário)
  • Aquisição de token: ocorre automaticamente durante a entrada
  • Considerações especiais: consentimento incremental, tratamento de falhas de consentimento

Leia o guia Aplicativos Web

Integração da API Web

As APIs Web usam o fluxo on-Behalf-Of para trocar um token de usuário de entrada por um novo token com escopo para a API downstream.

  • Padrão primário: fluxo on-Behalf-Of (OBO)
  • Token acquisition: Transação de token de entrada por token de destino
  • Considerações especiais: processos de execução longa, cache de token, identidades de agente.

Ler o guia de APIs Web

Integração de aplicativos daemon

Aplicativos daemon se autenticam como eles mesmos sem um usuário conectado.

  • Padrão primário: permissões de aplicativo (somente aplicativo)
  • Aquisição de token: fluxo de credenciais do cliente
  • Considerações especiais: sem contexto de usuário, requer consentimento do administrador
  • Avançado: agentes autônomos, identidades de usuário do agente

Leia o guia de Aplicativos Daemon

Tratamento de erros para aquisição de token

Todos os métodos de aquisição de token podem gerar exceções que seu aplicativo deve manipular. Em aplicativos Web, o atributo manipula o [AuthorizeForScope(scopes)] consentimento incremental do usuário ou a nova assinatura.

O exemplo a seguir mostra como capturar e lidar com exceções comuns de aquisição de 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");
}

Cenários de erro comuns

A tabela a seguir lista as exceções mais comuns e como resolvê-las.

Exceção Meaning Solução
MicrosoftIdentityWebChallengeUserException Consentimento do usuário necessário Redirecione para Microsoft Entra ID para obter consentimento. Usar o atributo AuthorizeForScopes ou a classe ConsentHandler
MsalUiRequiredException Autenticação interativa necessária Lidar com desafios em aplicativos web
MsalServiceException erro de serviço do Microsoft Entra ID Verificar a configuração, tentar novamente
HttpRequestException Erro de API downstream Tratar erros específicos da API

Pacotes NuGet necessários

Escolha o pacote que corresponde ao seu cenário. A tabela a seguir lista cada pacote e quando usá-lo.

Package Propósito Quando usar
Microsoft. Identity.Web.TokenAcquisition Serviços de aquisição de token Pacote principal
Microsoft. Identity.Web.DownstreamApi Abstração de IDownstreamApi Chamando APIs REST
Microsoft. Identity.Web.GraphServiceClient integração Microsoft Graph Chamada do Microsoft Graph (guia de migração)
Microsoft. Identity.Web. Azure integração SDK do Azure Chamando serviços de Azure
Microsoft. Identity.Web ASP.NET Core aplicativos Web e APIs Web ASP.NET Core
Microsoft. Identity.Web.OWIN ASP.NET aplicativos Web OWIN e APIs Web OWIN

Explore esses guias para obter instruções passo a passo detalhadas e cenários avançados.