Migrar aplicações clientes confidenciais do ADAL.NET para o MSAL.NET

Neste guia prático, irá migrar uma aplicação cliente confidencial do Azure Active Directory Authentication Library for .NET (ADAL.NET) para a Biblioteca de Autenticação da Microsoft for .NET (MSAL.NET). Aplicações cliente confidenciais incluem aplicações web, APIs web e aplicações daemon que chamam outro serviço em seu próprio nome. Para mais informações sobre aplicações confidenciais, consulte Fluxos de autenticação e cenários de aplicação. Se a sua aplicação for baseada no ASP.NET Core, veja Microsoft. Identidade.Web.

Para registos de aplicações:

  • Não precisa de criar um novo registo de aplicação. (Mantém o mesmo ID de cliente.)
  • Não precisas de alterar as pré-autorizações (permissões da API consentidas pelo administrador).

Etapas de migração

  1. Encontra o código que usa ADAL.NET na tua aplicação.

    O código que utiliza o ADAL numa aplicação cliente confidencial instancia AuthenticationContext e invoca AcquireTokenByAuthorizationCode ou uma das substituições de AcquireTokenAsync com os seguintes parâmetros:

    • Uma resourceId cadeia de caracteres. Esta variável é o URI do ID da aplicação da API web que pretende chamar.
    • Uma instância de IClientAssertionCertificate ou ClientAssertion. Esta instância fornece as credenciais do cliente para a sua aplicação para provar a identidade da sua aplicação.
  2. Depois de identificar que tem aplicações que usam ADAL.NET, instale o pacote MSAL.NET NuGet Microsoft. Identity.Client e atualize as referências da sua biblioteca de projetos. Para mais informações, consulte Instalar um pacote NuGet. Para usar serializadores de cache de tokens, instale Microsoft.Identity.Web.TokenCache.

  3. Atualize o código de acordo com o cenário confidencial do cliente. Alguns passos são comuns e aplicam-se a todos os cenários confidenciais do cliente. Outros passos são únicos para cada cenário.

    Cenários confidenciais para clientes:

Podes ter fornecido um wrapper em ADAL.NET para gerir certificados e cache. Este guia utiliza a mesma abordagem para ilustrar o processo de migração do ADAL.NET para o MSAL.NET. No entanto, este código é apenas para fins de demonstração. Não copies ou coles estes wrappers nem os integres no teu código tal como estão.

Migrar aplicações daemon

Cenários de daemon utilizam o fluxo de credenciais do cliente OAuth2.0. Também são chamadas de chamadas entre serviços. A sua aplicação adquire um token em nome próprio, não em nome do utilizador.

Descobre se o teu código usa cenários de demónio

O código ADAL da sua aplicação utiliza cenários de daemon se contiver uma chamada a AuthenticationContext.AcquireTokenAsync com os seguintes parâmetros:

  • Um recurso (ID da aplicação URI) como primeiro parâmetro
  • IClientAssertionCertificate ou ClientAssertion como segundo parâmetro

AuthenticationContext.AcquireTokenAsync não tem um parâmetro do tipo UserAssertion. Se for esse o caso, então a sua aplicação é uma API Web e utiliza o cenário API Web que chama APIs Web a jusante.

Atualizar o código dos cenários de demónios

Os seguintes passos para atualizar o código aplicam-se a todos os cenários confidenciais do cliente:

  1. Adicione o espaço de nomes MSAL.NET ao seu código-fonte: using Microsoft.Identity.Client;.
  2. Em vez de instanciar AuthenticationContext, use ConfidentialClientApplicationBuilder.Create para instanciar IConfidentialClientApplication.
  3. Em vez da cadeia de caracteres resourceId, o MSAL.NET utiliza âmbitos. Como as aplicações que utilizam ADAL.NET são pré-autorizadas, pode sempre usar os seguintes âmbitos: new string[] { $"{resourceId}/.default" }.
  4. Substitua a chamada para AuthenticationContext.AcquireTokenAsync por uma chamada para IConfidentialClientApplication.AcquireTokenXXX, onde XXX depende do seu cenário.

Neste caso, substitua a chamada para AuthenticationContext.AcquireTokenAsync por uma chamada para IConfidentialClientApplication.AcquireTokenClient.

Aqui está uma comparação do código ADAL.NET e MSAL.NET para cenários de daemons:

ADAL

MSAL

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public partial class AuthWrapper
{
const string ClientId = "Guid (AppID)";
const string authority 
= "https://login.microsoftonline.com/{tenant}";
// App ID URI of web API to call
const string resourceId = "https://target-api.domain.com";
X509Certificate2 certificate = LoadCertificate();



public async Task<AuthenticationResult> GetAuthenticationResult()
{


var authContext = new AuthenticationContext(authority);
var clientAssertionCert = new ClientAssertionCertificate(
ClientId,
certificate);


var authResult = await authContext.AcquireTokenAsync(
resourceId,
clientAssertionCert,
);

return authResult;
}
}
using Microsoft.Identity.Client;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public partial class AuthWrapper
{
const string ClientId = "Guid (Application ID)";
const string authority 
= "https://login.microsoftonline.com/{tenant}";
// App ID URI of web API to call
const string resourceId = "https://target-api.domain.com";
X509Certificate2 certificate = LoadCertificate();

IConfidentialClientApplication app;

public async Task<AuthenticationResult> GetAuthenticationResult()
{

var app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithCertificate(certificate)
.WithAuthority(authority)
.Build();

// Setup token caching https://learn.microsoft.com/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=aspnet
// For example, for an in-memory cache with 1GB limit, use  
app.AddInMemoryTokenCache(services =>
{
// Configure the memory cache options
services.Configure<MemoryCacheOptions>(options =>
{
options.SizeLimit = 1024 * 1024 * 1024; // in bytes (1 GB of memory)
});
}

var authResult = await app.AcquireTokenForClient(
new [] { $"{resourceId}/.default" })
// .WithTenantId(specificTenant)
// See https://aka.ms/msal.net/withTenantId
.ExecuteAsync()
.ConfigureAwait(false);

return authResult;
}
}

Tire partido do armazenamento em cache de tokens

Se não configurares a cache do token, o emissor do token vai limitar-te, resultando em erros. Também é muito mais rápido obter um token da cache (10-20 ms) do que obtê-lo a partir do ESTS (500-30000 ms).

Se quiser implementar uma cache de token distribuída, veja Cache de token para uma aplicação web ou API web (aplicação cliente confidencial).

Saiba mais sobre o cenário dos daemons e como é implementado com MSAL.NET ou Microsoft. Identity.Web em novas aplicações.

Benefícios do MSAL

Os principais benefícios do MSAL.NET para a sua aplicação incluem:

  • Resiliência. O MSAL.NET ajuda a tornar a sua aplicação resiliente através de:

    • Benefícios do Serviço de Credenciais em Cache (CCS) do Microsoft Entra ID. O CCS funciona como backup da Microsoft Entra.
    • Renovação proativa de tokens se a API que invoca suportar tokens de longa duração através de avaliação contínua de acesso.
  • Security. Pode adquirir tokens de Prova de Posse (PoP) se a API web que pretende chamar o exigir. Para obter mais detalhes, consulte tokens de prova de posse no MSAL.NET

  • Desempenho e escalabilidade. Se não precisares de partilhar a cache com ADAL.NET, desativa a compatibilidade de cache legada ao criar a aplicação cliente confidencial (.WithLegacyCacheCompatibility(false)) para aumentar significativamente o desempenho.

    app = ConfidentialClientApplicationBuilder.Create(ClientId)
            .WithCertificate(certificate)
            .WithAuthority(authority)
            .WithLegacyCacheCompatibility(false)
            .Build();
    

Troubleshooting

MsalServiceException

A seguinte informação de resolução de problemas faz duas suposições:

  • O teu código ADAL.NET estava a funcionar.
  • Migraste para MSAL mantendo o mesmo ID de cliente.

Se obtiver uma exceção com uma das seguintes mensagens:

AADSTS700027: Client assertion contains an invalid signature. [Reason - The key was not found.]

AADSTS90002: Tenant 'aaaabbbb-0000-cccc-1111-dddd2222eeee' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID. Check with your subscription administrator.

Resolva a exceção usando estes passos:

  1. Confirme que está a usar a versão mais recente do MSAL.NET.
  2. Confirme que o host de autoridade que definiu ao construir a aplicação cliente confidencial e o host de autoridade que usou com o ADAL são semelhantes. Em particular, trata-se da mesma nuvem (Azure Government, Microsoft Azure operado pela 21Vianet ou Azure Alemanha)?

MsalClientException

Em aplicações multitenant, especifique uma autoridade comum ao criar a aplicação para visar um inquilino específico, como o inquilino do utilizador ao chamar uma API da Web. Desde a versão 4.37.0 do MSAL.NET, quando especifica .WithAzureRegion ao criar a aplicação, já não pode especificar a autoridade utilizando .WithAuthority durante os pedidos de token. Se o fizer, receberá o seguinte erro ao atualizar a partir de versões anteriores do MSAL.NET:

MsalClientException - "You configured WithAuthority at the request level, and also WithAzureRegion. This is not supported when the environment changes from application to request. Use WithTenantId at the request level instead."

Para remediar este problema, substitua .WithAuthority na expressão AcquireTokenXXX por .WithTenantId. Especifique o inquilino usando um GUID ou um nome de domínio.

Passos seguintes

Saiba mais sobre: