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

Microsoft.Identity.Web oferece múltiplas abordagens para efetuar chamadas para APIs a jusante — incluindo Microsoft Graph, serviços da Azure e APIs REST personalizadas — a partir das suas aplicações ASP.NET Core, OWIN ou .NET. Este artigo ajuda-o a escolher a abordagem certa para o seu cenário e a começar rapidamente.

Seleção de abordagem

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

Tipo de API / Cenário Decisão / Critérios Cliente/Turma Recomendada
Microsoft Graph Precisa de ligar às APIs da Microsoft Graph GraphServiceClient
SDK do Azure (Storage, KeyVault, etc.) Precisas de chamar APIs do Azure (SDK do Azure) MicrosoftIdentityTokenCredential com clientes do SDK do Azure
API personalizada com vinculação de token Segurança reforçada com ligação de certificados (mTLS PoP) IDownstreamApi com ProtocolScheme: "MTLS_POP"
API personalizada com vinculação de token Segurança reforçada com integração com HttpClient (mTLS PoP) MicrosoftIdentityMessageHandler com ProtocolScheme: "MTLS_POP"
API Personalizado Simples, configurável IDownstreamApi
API Personalizado usando HttpClient + handler de delegação MicrosoftIdentityMessageHandler
API Personalizado usando o seu HttpClient IAuthorizationHeaderProvider

Comparação de abordagens por complexidade e flexibilidade

A tabela seguinte resume cada abordagem pelo seu caso de uso pretendido, nível de complexidade e flexibilidade.

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

Padrões de aquisição de tokens

Microsoft. O Identity.Web suporta três principais padrões de aquisição de tokens:

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

Utilize permissões delegadas quando a sua aplicação atua em nome de um utilizador com sessão de registo.

  • Cenário: A aplicação web chama a API em nome do utilizador com sessão iniciada, bem como a identidade do agente autónomo.
  • Tipo de token: Token de acesso com permissões delegadas
  • Métodos: CreateAuthorizationHeaderForUserAsync(), GetForUserAsync()

Permissões de aplicação (tokens apenas de aplicação)

Use permissões da aplicação quando não houver utilizador presente e a aplicação se autenticar por si mesma.

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

Fluxo On-Behalf-Of (OBO)

Use o fluxo OBO quando uma API web precisar de chamar outra API downstream, preservando a identidade do utilizador.

  • Cenário: A Web API recebe token de utilizador, chama outra API em nome desse utilizador e agentes interativos.
  • Tipo de token: Novo token de acesso via fluxo OBO
  • Métodos: CreateAuthorizationHeaderForUserAsync() a partir do contexto da API web

Ligação de token (mTLS PoP)

A ligação de tokens adiciona uma camada extra de segurança ao ligar criptograficamente os tokens de acesso aos certificados X.509.

  • Cenário: Segurança reforçada onde os tokens estão criptograficamente ligados a certificados conforme o RFC 8705
  • Tipo de token: Token de acesso com vinculação de certificado (cnf claim)
  • Métodos: GetForAppAsync() com ProtocolScheme: "MTLS_POP"
  • Segurança: Previne o roubo de tokens ao vincular tokens a certificados específicos

Saiba mais sobre Ligação de Tokens com o MTLS PoP

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

Os exemplos seguintes demonstram cada abordagem com código de ponta a ponta que pode adaptar à sua aplicação.

O exemplo seguinte regista GraphServiceClient e usa-o para fazer chamadas à Microsoft Graph em nome do utilizador que iniciou sessão e como uma chamada apenas da aplicação.

// 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 integração Microsoft Graph

Migração do GraphServiceClient e utilização detalhada

O exemplo seguinte regista MicrosoftIdentityTokenCredential e passa-o 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 integração SDK do Azure

O exemplo seguinte configura uma API downstream nomeada em appsettings.json e chama-a com tokens delegados e exclusivos da aplicação.

// 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 o IDownstreamApi

Ligação de tokens com MTLS PoP (segurança reforçada)

A ligação de tokens proporciona segurança reforçada ao vincular criptograficamente tokens de acesso a certificados X.509. Mesmo que um token seja interceptado, não pode 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 tokens: Tokens roubados são inúteis sem o certificado
  • Prevenção de ataques de repetição: Os tokens não podem ser reproduzidos de diferentes clientes
  • Alinhamento zero trust: Forte ligação criptográfica entre cliente e token

Saiba mais sobre a Ligação de Tokens (mTLS PoP)

MicrosoftIdentityMessageHandler (para integração com HttpClient)

O exemplo seguinte adiciona um handler de delegação a um HttpClient para que cada pedido de saída inclua automaticamente um cabeçalho de autorização. O handler regista os escopos no arranque, e os pedidos individuais podem sobrepor 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 o MicrosoftIdentityMessageHandler

IAuthorizationHeaderProvider (máxima flexibilidade)

O exemplo seguinte recupera diretamente um cabeçalho de autorização para que possa anexá-lo a qualquer pedido HTTP juntamente 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 suporta tanto a configuração JSON como a configuração baseada em código.

configuração do appsettings.json

O JSON seguinte mostra uma configuração típica que regista 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 aplicações de daemon/consola, defina appsettings.json as propriedades: "Copiar para o Diretório de Saída" = "Copiar se for mais recente"

Saiba mais sobre a configuração de credenciais

Configuração baseada em código

Também pode configurar credenciais e APIs downstream inteiramente em código, como mostra o exemplo seguinte.

// 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 para cenários

A melhor abordagem depende de onde está a chamar a API:

Integração com aplicações web

As aplicações web normalmente chamam APIs a jusante em nome do utilizador autenticado.

  • Padrão primário: Permissões delegadas (em nome do utilizador)
  • Aquisição de tokens: Acontece automaticamente durante o início de sessão
  • Considerações especiais: Consentimento incremental, lidar com falhas de consentimento

Leia o guia Aplicações Web

Integração com API Web

As APIs Web utilizam o fluxo On-Behalf-Of para trocar um token de utilizador recebido por um novo token adequado para a API subsequente.

  • Padrão primário: Fluxo On-Behalf-Of (OBO)
  • Aquisição de tokens: Trocar o token recebido por um token a jusante
  • Considerações especiais: Processos de longa duração, cache de tokens, identidades de agentes.

Leia o guia das APIs Web

Integração de aplicações daemon

As aplicações daemon autenticam-se como elas próprias sem um utilizador com sessão iniciada.

  • Padrão principal: Permissões de aplicação (apenas para aplicação)
  • Aquisição de tokens: Fluxo de credenciais do cliente
  • Considerações especiais: Sem contexto de utilizador, requer consentimento do administrador
  • Avançado: Agentes autónomos, identidades de utilizador de agentes

Leia o guia de Aplicações Daemon

Tratamento de erros para aquisição de tokens

Todos os métodos de aquisição de tokens podem lançar exceções que a sua aplicação deve gerir. Nas aplicações web, o [AuthorizeForScope(scopes)] atributo gere o consentimento incremental do utilizador ou a renovação de assinatura.

O exemplo seguinte mostra como detetar e lidar com exceções comuns de aquisição de tokens.

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 seguinte lista as exceções mais comuns e como resolvê-las.

Exceção Meaning Solução
MicrosoftIdentityWebChallengeUserException É necessário consentimento do utilizador Redirecionar para o Microsoft Entra ID para obter consentimento. Use o atributo AuthorizeForScopes ou a classe ConsentHandler
MsalUiRequiredException É necessária autenticação interativa Lidar com aplicações web com desafios
MsalServiceException Erro do serviço Microsoft Entra ID Verificar a configuração, tentar novamente
HttpRequestException Erro de API a jusante Lidar com erros específicos da API

Pacotes NuGet necessários

Escolhe o pacote que se adequa ao teu cenário. A tabela seguinte lista cada pacote e quando o utilizar.

Package Purpose Quando utilizar
Microsoft. Identity.Web.TokenAcquisition Serviços de aquisição de tokens Pacote núcleo
Microsoft. Identity.Web.DownstreamApi Abstração IDownstreamApi Chamada de APIs REST
Microsoft. Identity.Web.GraphServiceClient Integração com Microsoft Graph Calling Microsoft Graph (guia de migração)
Microsoft.Identity.Web.Azure SDK do Azure integration Chamar serviços Azure
Microsoft.Identity.Web Aplicações web e APIs web ASP.NET Core ASP.NET Core
Microsoft.Identity.Web.OWIN ASP.NET Aplicações web OWIN e APIs web OWIN

Explore estes guias para passo a passo detalhados e cenários avançados.