Diferenças entre ADAL.NET e MSAL.NET apps

Migrar as suas aplicações de usar a ADAL para usar o MSAL vem com benefícios de segurança e resiliência. Este artigo descreve diferenças entre MSAL.NET e ADAL.NET. Na maioria dos casos pretende utilizar MSAL.NET e a plataforma de identidade da Microsoft, que é a última geração de Bibliotecas de Autenticação do Microsoft. Utilizando MSAL.NET, adquire fichas para os utilizadores que se inscrevam na sua aplicação com Azure AD (contas de trabalho e escola), contas microsoft (pessoais) (MSA) ou Azure AD B2C.

Se já está familiarizado com ADAL.NET e o AD Azure para programadores (v1.0), conheça o que há de diferente na plataforma de identidade da Microsoft?. Ainda precisa de utilizar ADAL.NET se a sua aplicação precisar de assinar em utilizadores com versões anteriores dos Serviços da Federação de Diretórios Ativos (ADFS). Para mais informações, consulte o suporte da ADFS.

REDE ADAL REDE MSAL
Pacotes NuGet e Espaços de Nome A ADAL foi consumida a partir do pacote Microsoft.IdentityModel.Clients.ActiveDirectory NuGet. O espaço de nome era Microsoft.IdentityModel.Clients.ActiveDirectory. Adicione o pacote Microsoft.Identity.Client NuGet e use o Microsoft.Identity.Client espaço de nomes. Se está a construir uma aplicação confidencial para clientes, consulte a Microsoft.Identity.Web.
Âmbitos e recursos ADAL.NET adquire fichas para recursos. MSAL.NET adquire fichas para âmbitos. Vários MSAL.NET AcquireTokenXXX sobreposições requerem um parâmetro chamado scopes(IEnumerable<string> scopes). Este parâmetro é uma lista simples de cordas que declaram as permissões e recursos que são solicitados. Os âmbitos bem conhecidos são os âmbitos do Microsoft Graph. Também pode aceder aos recursos v1.0 utilizando MSAL.NET.
Classes principais ADAL.NET utilizou o AutenticaçãoContexto como representação da sua ligação ao Serviço de Token de Segurança (STS) ou servidor de autorização, através de uma Autoridade. MSAL.NET é projetado em torno de aplicações de clientes. Define interfaces IPublicClientApplication para aplicações de clientes públicos e IConfidentialClientApplication para aplicações confidenciais de clientes, bem como uma interface IClientApplicationBase base para o contrato comum a ambos os tipos de aplicações.
Aquisição de Token Em clientes públicos, a ADAL utiliza AcquireTokenAsync e AcquireTokenSilentAsync para chamadas de autenticação. Nos clientes públicos, a MSAL utiliza AcquireTokenInteractive e AcquireTokenSilent para as mesmas chamadas de autenticação. Os parâmetros são diferentes dos ADAL.

Nas aplicações confidenciais de clientes, existem métodos de aquisição simbólicos com um nome explícito dependendo do cenário. Outra diferença é que, em MSAL.NET, já não tem de passar na aplicação ClientID em todas as chamadas AcquireTokenXX. O ClientID conjunto é definido apenas uma vez quando se constrói IPublicClientApplication ou IConfidentialClientApplication. .
IAccount e IUser A ADAL define a noção de utilizador através da interface IUser. No entanto, um utilizador é um humano ou um agente de software. Como tal, um utilizador pode possuir uma ou mais contas na plataforma de identidade da Microsoft (várias contas AD AZure, Azure AD B2C, contas pessoais da Microsoft). O utilizador também pode ser responsável por uma ou mais contas da plataforma de identidade da Microsoft. MSAL.NET define o conceito de conta (através da interface IAccount). A interface IAccount representa informações sobre uma única conta. O utilizador pode ter várias contas em diferentes inquilinos. MSAL.NET fornece uma melhor informação em cenários de hóspedes, uma vez que a informação da conta de casa é fornecida. Pode ler mais sobre as diferenças entre iUser e IAccount.
Persistência de Cache ADAL.NET permite alargar a TokenCache classe para implementar a funcionalidade de persistência desejada nas plataformas sem um armazenamento seguro (.NET Framework e .NET core) utilizando os BeforeAccess, e BeforeWrite métodos. Para mais detalhes, consulte a serialização da cache simbólica em ADAL.NET. MSAL.NET faz da cache simbólica uma classe selada, removendo a capacidade de estender. Como tal, a sua implementação da persistência da cache simbólica deve ser na forma de uma classe de ajudante que interage com a cache simbólica selada. Esta interação é descrita na serialização da cache simbólica em MSAL.NET artigo. A serialização de uma aplicação de cliente público (Ver cache simbólico para uma aplicação de cliente público), é diferente da de uma aplicação confidencial de cliente (ver cache simbólico para uma aplicação web ou API web).
Autoridade comum A ADAL usa Azure AD v1.0. https://login.microsoftonline.com/common autoridade em Azure AD v1.0 (que a ADAL utiliza) permite que os utilizadores inscrevam-se usando qualquer conta de organização AAD (trabalho ou escola). Azure AD v1.0 não permite iniciar sômpa com contas pessoais da Microsoft. Para mais informações, consulte a validação da autoridade em ADAL.NET. A MSAL utiliza a Azure AD v2.0. https://login.microsoftonline.com/common autoridade em Azure AD v2.0 (que a MSAL utiliza) permite que os utilizadores assinem com qualquer conta de organização AAD (trabalho ou escola) ou com uma conta pessoal da Microsoft. Para restringir a inscrição na utilização apenas de contas de organização (trabalho ou conta escolar) no MSAL, terá de utilizar o https://login.microsoftonline.com/organizations ponto final. Para mais detalhes, consulte o authority parâmetro na aplicação do cliente público.

Subvenções apoiadas

Segue-se um resumo comparando MSAL.NET e ADAL.NET subvenções apoiadas para aplicações públicas e confidenciais de clientes.

Aplicações de clientes públicos

A imagem que se segue resume algumas das diferenças entre ADAL.NET e MSAL.NET para uma aplicação de cliente público.

Screenshot showing some of the differences between ADAL.NET and MSAL.NET for a public client application.

Aqui estão as bolsas suportadas em ADAL.NET e MSAL.NET para aplicações desktop e mobile.

Concessão MSAL.NET ADAL.NET
Interativo Aquisição de fichas interativamente em MSAL.NET Auth Interativo
Autenticação integrada do Windows Autenticação integrada do Windows Autenticação integrada no Windows (Kerberos)
Nome de utilizador / Palavra-passe Autenticação do nome de utilizador-senha Aquisição de fichas com nome de utilizador e senha
Fluxo de código do dispositivo Fluxo de código do dispositivo Perfil do dispositivo para dispositivos sem navegadores web

Aplicações confidenciais de clientes

A imagem a seguir resume algumas das diferenças entre ADAL.NET e MSAL.NET para uma aplicação confidencial do cliente.

Screenshot showing some of the differences between ADAL.NET and MSAL.NET for a confidential client application.

Aqui estão as bolsas suportadas em ADAL.NET, MSAL.NET e Microsoft.Identity.Web para aplicações web, APIs web e aplicações daemon.

Tipo de App Concessão MSAL.NET ADAL.NET
Web app, web API, daemon Credenciais de Cliente A credencial do cliente flui em MSAL.NET A credencial do cliente flui em ADAL.NET
API Web Em nome de Em nome de MSAL.NET Serviço para atender chamadas em nome do utilizador com ADAL.NET
Aplicação Web Código Auth Aquisição de fichas com códigos de autorização em aplicações web com MSAL.NET Aquisição de fichas com códigos de autorização em aplicações web com ADAL.NET

Migrando de ADAL 2.x com fichas de atualização

Em ADAL.NET v2. X, os tokens de atualização foram expostos permitindo-lhe desenvolver soluções em torno da utilização destes tokens, caching-los e usando os AcquireTokenByRefreshToken métodos fornecidos por ADAL 2.x.

Algumas dessas soluções foram utilizadas em cenários como:

  • Serviços de longa duração que fazem ações que incluem dashboards refrescantes para os utilizadores quando os utilizadores já não estão conectados/inscritos na app.
  • Cenários webFarm para permitir que o cliente leve o token de atualização para o serviço web (o caching é feito lado do cliente, cookie encriptado e não o lado do servidor).

MSAL.NET não expõe fichas de atualização por razões de segurança. A MSAL lida com fichas refrescantes para si.

Felizmente, MSAL.NET tem uma API que lhe permite migrar os seus tokens de atualização anteriores (adquiridos com ADAL) para o IConfidentialClientApplication:

/// <summary>
/// Acquires an access token from an existing refresh token and stores it and the refresh token into
/// the application user token cache, where it will be available for further AcquireTokenSilent calls.
/// This method can be used in migration to MSAL from ADAL v2 and in various integration
/// scenarios where you have a RefreshToken available.
/// (see https://aka.ms/msal-net-migration-adal2-msal2)
/// </summary>
/// <param name="scopes">Scope to request from the token endpoint.
/// Setting this to null or empty will request an access token, refresh token and ID token with default scopes</param>
/// <param name="refreshToken">The refresh token from ADAL 2.x</param>
IByRefreshToken.AcquireTokenByRefreshToken(IEnumerable<string> scopes, string refreshToken);

Com este método, pode fornecer o token de atualização previamente usado juntamente com quaisquer âmbitos (recursos) que desejar. O token de atualização será trocado por um novo e incorporado na sua aplicação.

Como este método se destina a cenários que não são típicos, não é facilmente acessível com o IConfidentialClientApplication sem primeiro casting para IByRefreshToken.

O código abaixo mostra algum código de migração numa aplicação confidencial do cliente.

TokenCache userCache = GetTokenCacheForSignedInUser();
string rt = GetCachedRefreshTokenForSignedInUser();

IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(clientId)
 .WithAuthority(Authority)
 .WithRedirectUri(RedirectUri)
 .WithClientSecret(ClientSecret)
 .Build();
IByRefreshToken appRt = app as IByRefreshToken;

AuthenticationResult result = await appRt.AcquireTokenByRefreshToken(null, rt)
                                         .ExecuteAsync()
                                         .ConfigureAwait(false);

GetCachedRefreshTokenForSignedInUser recupera o token refresh que foi armazenado em algum armazenamento por uma versão anterior da aplicação que costumava usar ADAL 2.x. GetTokenCacheForSignedInUser deserializa uma cache para o utilizador inscrito (uma vez que as aplicações confidenciais do cliente devem ter uma cache por utilizador).

Um token de acesso e um token de ID são devolvidos no AuthenticationResult valor enquanto o novo token de atualização é armazenado na cache. Você também pode usar este método para vários cenários de integração onde você tem um token de atualização disponível.

v1.0 e v2.0 fichas

Existem duas versões de fichas: tokens v1.0 e tokens v2.0. O ponto final v1.0 (utilizado pela ADAL) emite fichas de identificação v1.0 enquanto o ponto final v2.0 (usado por MSAL) emite fichas de identificação v2.0. No entanto, ambos os pontos finais emitem tokens de acesso da versão do token que a API web aceita. Uma propriedade do manifesto de aplicação da API web permite que os desenvolvedores escolham qual versão de token é aceite. Consulte accessTokenAcceptedVersion na documentação de referência manifesto do pedido .

Para obter mais informações sobre os tokens de acesso v1.0 e v2.0, consulte os tokens de acesso do Azure Ative Directory.

Exceções

Interação necessárias exceções

Utilizando MSAL.NET, apanha-se MsalUiRequiredException como descrito no AcquireTokenSilent.

catch(MsalUiRequiredException exception)
{
 try {"try to authenticate interactively"}
}

Para mais detalhes, consulte erros e exceções no MSAL.NET

ADAL.NET tinham exceções menos explícitas. Por exemplo, quando a autenticação silenciosa falhou na ADAL, o procedimento foi pegar na exceção e procurar o código de user_interaction_required erro:

catch(AdalException exception)
{
 if (exception.ErrorCode == "user_interaction_required")
 {
  try
  {“try to authenticate interactively”}}
 }
}

Para mais detalhes, consulte o padrão recomendado para adquirir um token em aplicações de clientes públicos com ADAL.NET.

Comportamento do pedido

Comportamento rápido em MSAL.NET equivale a comportamento rápido em ADAL.NET:

ADAL.NET MSAL.NET Description
PromptBehavior.Auto NoPrompt O Azure AD escolhe o melhor comportamento (iniciar sessão em utilizadores em silêncio se estiver assinado com apenas uma conta, ou exibir o seletor de conta se estiver assinado com várias contas).
PromptBehavior.Always ForceLogin Reinicia a caixa de entrada e obriga o utilizador a reentrar nas suas credenciais.
PromptBehavior.RefreshSession Consent Força o utilizador a consentir novamente com todas as permissões.
PromptBehavior.Never Never Não use; em vez disso, use o padrão recomendado para aplicações de clientes públicos.
PromptBehavior.SelectAccount SelectAccount Apresenta o seletor de conta e obriga o utilizador a selecionar uma conta.

Tratamento de reclamações desafia exceções

Nos momentos em que adquire um token, a Azure AD lança uma exceção no caso de um recurso exigir mais reclamações do utilizador (por exemplo, autenticação de dois fatores).

Em MSAL.NET, as exceções de impugnação de reivindicação são tratadas da seguinte forma:

  • Os Claims são surgidos no MsalServiceException.
  • Há um .WithClaim(claims) método que pode aplicar-se aos AcquireTokenXXX construtores.

Para mais detalhes, consulte Handling MsalUiRequiredException.

Em ADAL.NET, as exceções de impugnação de reivindicação foram tratadas da seguinte forma:

  • AdalClaimChallengeException é uma exceção (derivando de AdalServiceException). O Claims membro contém algum fragmento JSON com as alegações, que são esperadas.
  • A aplicação do cliente público que recebe esta exceção necessária para chamar a anulação AcquireTokenInteractive tendo um parâmetro de reclamações. Esta sobreposição AcquireTokenInteractive nem sequer tenta acertar na cache porque não é necessário. A razão é que o símbolo na cache não tem as reivindicações certas (caso contrário, um AdalClaimChallengeException não teria sido atirado). Como tal, não há necessidade de olhar para a cache. O ClaimChallengeException pode ser recebido num WebAPI fazendo OBO, mas a AcquireTokenInteractive necessidade de ser chamado em uma aplicação de cliente público chamando esta API web.

Para mais detalhes, incluindo amostras, consulte o manuseamento da AdalClaimChallengeException.

Âmbitos

A ADAL usa o conceito de recursos com resourceId cordas, MSAL.NET, no entanto, usa âmbitos. A lógica utilizada pela Azure AD é a seguinte:

  • Para o ponto final ADAL (v1.0) com um token de acesso v1.0 (o único possível), aud=resource.
  • Para o MSAL (ponto final v2.0) pedir um sinal de acesso para um recurso que aceite fichas v2.0, aud=resource.AppId.
  • Para o MSAL (ponto final v2.0) pedir um token de acesso para um recurso que aceite um token de acesso v1.0, a Azure AD analisa o público desejado a partir do âmbito solicitado. Isto é feito tomando tudo antes do último corte e usando-o como identificador de recursos. Como tal, se https://database.windows.net espera uma audiência de https://database.windows.net/, terá de solicitar um âmbito de https://database.windows.net//.default (note o duplo corte antes de ./predefinição). Isto é ilustrado pelos exemplos 1 e 2 abaixo.

Exemplo 1

Se quiser adquirir fichas para uma aplicação que aceite tokens v1.0 (por exemplo, a Microsoft Graph API, ou seja https://graph.microsoft.com), terá de criar scopes através da concatetação de um identificador de recursos pretendido com uma permissão OAuth2 desejada para esse recurso.

Por exemplo, para aceder ao nome do utilizador através de uma API web v1.0 cuja aplicação ID URI é ResourceId, você gostaria de usar:

var scopes = new [] { ResourceId+"/user_impersonation" };

Se quiser ler e escrever com MSAL.NET Azure Ative Directory utilizando a API do Gráfico microsoft (https://graph.microsoft.com/), criaria uma lista de âmbitos como no corte de código abaixo:

string ResourceId = "https://graph.microsoft.com/"; 
string[] scopes = { ResourceId + "Directory.Read", ResourceId + "Directory.Write" }

Exemplo 2

Se o recursoId terminar com um '/', terá de ter um '/' duplo ao escrever o valor de âmbito. Por exemplo, se pretender escrever o âmbito correspondente à AZure Resource Manager API (https://management.core.windows.net/), solicite o seguinte âmbito (note as duas barras).

var resource = "https://management.core.windows.net/"
var scopes = new[] {"https://management.core.windows.net//user_impersonation"};
var result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();

// then call the API: https://management.azure.com/subscriptions?api-version=2016-09-01

Isto porque a API gestora de recursos espera um corte na sua reivindicação de audiência (aud), e depois há um corte para separar o nome API do âmbito.

Se quiser adquirir um símbolo para todos os âmbitos estáticos de uma aplicação v1.0, criaria a sua lista de âmbitos como mostrado no corte de código abaixo:

ResourceId = "someAppIDURI";
var scopes = new [] { ResourceId+"/.default" };

Para um fluxo de credencial de cliente, o âmbito a passar também seria /.default. Este âmbito diz ao Azure AD: "todas as permissões ao nível da aplicação a que o administrador consentiu no registo da aplicação.

Passos seguintes

Migrar as suas aplicações de ADAL para MSALMigrar as suas ADAL.NET aplicações confidenciais de clientes para utilizar MSAL.NET