Como migrar um aplicativo JavaScript da ADAL.js para a MSAL.js
A MSAL.js (Biblioteca de Autenticação da Microsoft para JavaScript) 2.x, também conhecida como msal-browser
, é a biblioteca de autenticação recomendada para aplicativos JavaScript na plataforma de identidade da Microsoft. Este artigo destaca as alterações necessárias para migrar um aplicativo que usa a ADAL.js para a MSAL.js 2.x
Observação
É recomendado usar a MSAL.js 2.x em vez da MSAL.js 1.x. O fluxo de concessão de código de autenticação é mais seguro e permite que aplicativos de página única mantenham uma boa experiência de usuário, apesar das medidas de privacidade que navegadores como o Safari implementaram para bloquear cookies de terceiros, entre outros benefícios.
Pré-requisitos
- Configure Plataforma / Tipo de URL de Resposta como Aplicativo de página única no portal de Registro de Aplicativo (se você tiver outras plataformas adicionadas ao registro de aplicativo, como Web, verifique se os URIs de redirecionamento não se sobrepõem. Confira: Restrições de URI de redirecionamento)
- Forneça o polyfills aos recursos ES6 dos quais a MSAL.js depende (por exemplo, promessas) para executar seus aplicativos no Internet Explorer
- Migre seus aplicativos do Microsoft Entra para o ponto de extremidade v2, caso ainda não tenha feito isso
Instalar e importar MSAL
Há duas maneiras de instalar a biblioteca MSAL.js 2.x:
Via npm:
npm install @azure/msal-browser
Neste caso, dependendo do sistema de módulos, importe-o conforme mostrado abaixo:
import * as msal from "@azure/msal-browser"; // ESM
const msal = require('@azure/msal-browser'); // CommonJS
Via CDN:
Carregue o script na seção de cabeçalho do documento HTML:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://alcdn.msauth.net/browser/2.14.2/js/msal-browser.min.js"></script>
</head>
</html>
Para ver links alternativos sobre CDN e práticas recomendadas ao usá-la, veja Uso da CDN
Inicializar a MSAL
Na ADAL.js, você cria uma instância da classe AuthenticationContext, a qual expõe os métodos que você pode usar para obter a autenticação (login
, acquireTokenPopup
, e assim por diante). Este objeto atua como a representação da conexão do aplicativo com o servidor de autorização ou o provedor de identidade. Ao inicializar, o único parâmetro obrigatório é clientId:
window.config = {
clientId: "YOUR_CLIENT_ID"
};
var authContext = new AuthenticationContext(config);
Na MSAL.js, você instancia a classe PublicClientApplication. Como a ADAL.js, o construtor espera um objeto de configuração que contenha no mínimo o parâmetro clientId
. Para saber mais,veja Inicializar a MSAL.js
const msalConfig = {
auth: {
clientId: 'YOUR_CLIENT_ID'
}
};
const msalInstance = new msal.PublicClientApplication(msalConfig);
Na ADAL.js e na MSAL.js, o URI de autoridade é padronizado para https://login.microsoftonline.com/common
quando não é especificado.
Observação
Se você usar a autoridade https://login.microsoftonline.com/common
na v2.0, permitirá que os usuários entrem com qualquer conta Microsoft pessoal (MSA) ou da organização do Microsoft Entra. Na MSAL.js, para restringir o logon a qualquer conta do Microsoft Entra (mesmo comportamento da ADAL.js), use https://login.microsoftonline.com/organizations
.
Configurar a MSAL
Algumas das opções de configuração na ADAL.js que são usadas ao inicializar AuthenticationContext estão preteridas na MSAL.js, mas foram introduzidas outras novas. Veja a lista completa de opções disponíveis. É importante ressaltar que muitas dessas opções, exceto clientId
, podem ser substituídas durante a aquisição de tokens, o que permite que você as defina por solicitação. Por exemplo, é possível usar um URI de autoridade ou um URI de redirecionamento diferente daquele definido durante a inicialização ao adquirir tokens.
Além disso, não é necessário especificar a experiência de logon (ou seja, se ela acontece usando janelas pop-up ou redirecionando a página) nas opções de configuração. Em vez disso, a MSAL.js
expõe os métodos loginPopup
e loginRedirect
por meio da instância PublicClientApplication
.
Habilitar o registro em log
Na ADAL.js, você configura o log separadamente em qualquer lugar do código:
window.config = {
clientId: "YOUR_CLIENT_ID"
};
var authContext = new AuthenticationContext(config);
var Logging = {
level: 3,
log: function (message) {
console.log(message);
},
piiLoggingEnabled: false
};
authContext.log(Logging)
Na MSAL.js, o log faz parte das opções de configuração e é criado durante a inicialização de PublicClientApplication
:
const msalConfig = {
auth: {
// authentication related parameters
},
cache: {
// cache related parameters
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
}
const msalInstance = new msal.PublicClientApplication(msalConfig);
Alternar para a API da MSAL
Alguns dos métodos públicos na ADAL.js têm equivalentes na MSAL.js:
ADAL | MSAL | Observações |
---|---|---|
acquireToken |
acquireTokenSilent |
Renomeado e agora espera um objeto account |
acquireTokenPopup |
acquireTokenPopup |
Agora assíncrono e retorna uma promessa |
acquireTokenRedirect |
acquireTokenRedirect |
Agora assíncrono e retorna uma promessa |
handleWindowCallback |
handleRedirectPromise |
Necessário ao usar a experiência de redirecionamento |
getCachedUser |
getAllAccounts |
Renomeado e agora retorna uma matriz de contas. |
Embora os outros tenham sido preteridos, a MSAL.js oferece novos métodos:
ADAL | MSAL | Observações |
---|---|---|
login |
N/D | Preterido. Use loginPopup ou loginRedirect |
logOut |
N/D | Preterido. Use logoutPopup ou logoutRedirect |
N/D | loginPopup |
|
N/D | loginRedirect |
|
N/D | logoutPopup |
|
N/D | logoutRedirect |
|
N/D | getAccountByHomeId |
Filtra contas por ID da página inicial (oid + ID do locatário) |
N/D | getAccountLocalId |
Filtra contas por ID local (útil para ADFS) |
N/D | getAccountUsername |
Filtra contas por nome de usuário (se existir) |
Além disso, como a MSAL.js é implementada em TypeScript, ao contrário da ADAL.js, ela expõe diversos tipos e interfaces para uso em seus projetos. Confira a Referência da API do MSAL.js para saber mais.
Use escopos em vez de recursos
Uma diferença importante entre os pontos de extremidade do Azure Active Directory v1.0 quando comparado ao 2.0 diz respeito à maneira de acessar os recursos. Ao usar a ADAL.js com o ponto de extremidade da v1.0, primeiro você registrava uma permissão no portal de registro de aplicativo e, em seguida, solicitava um token de acesso para um recurso (como o Microsoft Graph), conforme mostrado abaixo:
authContext.acquireTokenRedirect("https://graph.microsoft.com", function (error, token) {
// do something with the access token
});
O MSAL.js só dá suporte ao ponto de extremidade v2.0. O ponto de extremidade da v2.0 emprega um modelo centrado no escopo para acessar recursos. Portanto, quando você solicita um token de acesso para um recurso, também precisará especificar o escopo desse recurso:
msalInstance.acquireTokenRedirect({
scopes: ["https://graph.microsoft.com/User.Read"]
});
Uma vantagem do modelo centrado no escopo é a capacidade de usar escopos dinâmicos. Ao criar aplicativos com o ponto de extremidade da v1.0, era preciso registrar o conjunto completo de permissões (chamadas de escopos estáticos) exigidas pelo aplicativo para o consentimento do usuário durante o logon. Na v2.0, você pode usar o parâmetro de escopo para solicitar as permissões no momento em que desejá-las (por isso escopos dinâmicos). Esses escopos permitem que o usuário forneça consentimento incremental aos escopos. Portanto, se no início você só quiser que o usuário entre em seu aplicativo e não precise de nenhum tipo de acesso, poderá fazê-lo. Se, posteriormente, você precisar que o usuário consiga ler o calendário, solicite o escopo do calendário nos métodos de token de aquisição e obtenha o consentimento do usuário. Para mais informações confira: Recursos e escopos
Usar promessas em vez de retornos de chamada
Na ADAL.js, os retornos de chamada são usados para qualquer operação depois que a autenticação é bem-sucedida e uma resposta é obtida:
authContext.acquireTokenPopup(resource, extraQueryParameter, claims, function (error, token) {
// do something with the access token
});
Na MSAL.js, são usadas promessas:
msalInstance.acquireTokenPopup({
scopes: ["User.Read"] // shorthand for https://graph.microsoft.com/User.Read
}).then((response) => {
// do something with the auth response
}).catch((error) => {
// handle errors
});
Você também pode usar a sintaxe assíncrona/await que vem com o ES8:
const getAccessToken = async() => {
try {
const authResponse = await msalInstance.acquireTokenPopup({
scopes: ["User.Read"]
});
} catch (error) {
// handle errors
}
}
Armazenar em cache e recuperar tokens
Como a ADAL.js, a MSAL.js armazena em cache tokens e outros artefatos de autenticação no armazenamento do navegador, usando a API de armazenamento na Web. Recomenda-se usar a opção sessionStorage
(veja: configuração), que é mais segura para o armazenamento de tokens adquiridos por seus usuários, mas localStorage
fornecerá o logon único em guias e sessões de usuário.
É importante ressaltar que você não deve acessar o cache diretamente. Você deve usar uma API apropriada da MSAL.js para recuperar artefatos de autenticação, como tokens de acesso ou contas de usuário.
Renovar tokens com tokens de atualização
A ADAL.js usa o fluxo implícito do OAuth 2.0, que não retorna tokens de atualização por motivos de segurança (os tokens de atualização têm tempo de vida maior do que os de acesso e, portanto, são mais perigosos nas mãos de agentes mal-intencionados). Portanto, a ADAL.js executa a renovação do token usando um IFrame oculto para que não seja repetidamente solicitado ao usuário que ele se autentique.
Com o fluxo de código de autenticação com suporte a PKCE, os aplicativos que usam a MSAL.js 2.x obtêm tokens de atualização com ID e tokens de acesso, que podem ser usados para renová-los. O uso de tokens de atualização é abstraído e os desenvolvedores não devem criar uma lógica sobre eles. A MSAL gerencia a renovação de tokens usando os tokens de atualização por si só. Seu cache de token anterior com a ADAL.js não será transferível para a MSAL.js, pois o esquema de cache de token mudou e é incompatível com o esquema usado na ADAL.js.
Lidar com erros e exceções
Ao usar a MSAL.js, o erro interaction_in_progress
é o tipo mais comum. Esse erro é lançado quando uma API interativa (loginPopup
, loginRedirect
, acquireTokenPopup
, acquireTokenRedirect
) é invocada enquanto outra ainda está em andamento. As APIs login*
e acquireToken*
são assíncronas, portanto, é necessário garantir que as promessas resultantes foram resolvidas antes de chamar outra.
Outro erro comum é interaction_required
. Ele geralmente é resolvido com a inicialização de um prompt de aquisição de token interativo. Por exemplo, a API da Web que você está tentando acessar pode ter uma política de Acesso Condicional em vigor, que pode exigir que o usuário execute a autenticação multifator (MFA). Nesse caso, lidar com o erro interaction_required
disparando acquireTokenPopup
ou acquireTokenRedirect
solicitará ao usuário a MFA, o que permite que ele a realize.
Outro erro comum que você pode enfrentar é consent_required
, que ocorre quando as permissões necessárias para obter um token de acesso para um recurso protegido não são consentidas pelo usuário. Como em interaction_required
, a solução para o erro consent_required
geralmente é iniciar um prompt de aquisição de token interativo, usando acquireTokenPopup
ou acquireTokenRedirect
.
Saiba mais em Erros comuns da MSAL.js e como lidar com eles
Usar a API de Eventos
A MSAL.js (>=v2.4) apresenta uma API de Eventos que você pode usar em seus aplicativos. Esses eventos estão relacionados ao processo de autenticação e ao que a MSAL está fazendo a qualquer momento, e podem ser usados para atualizar a IU, mostrar mensagens de erro, verificar se alguma interação está em andamento e assim por diante. Por exemplo, veja abaixo um retorno de chamada de evento que será chamado quando o processo de logon falhar por qualquer motivo:
const callbackId = msalInstance.addEventCallback((message) => {
// Update UI or interact with EventMessage here
if (message.eventType === EventType.LOGIN_FAILURE) {
if (message.error instanceof AuthError) {
// Do something with the error
}
}
});
Para fins de desempenho, é importante cancelar o registro dos retornos de chamada de evento quando eles não forem mais necessários. Veja mais: API de Eventos da MSAL.js
Lidar com diversas contas
A ADAL.js tem o conceito de um usuário para representar a entidade autenticada atualmente. A MSAL.js substitui usuários por contas, visto que um usuário pode ter mais de uma conta associada a eles. Isso também significa que agora você precisa controlar várias contas e escolher aquela com a qual trabalhar. O snippet abaixo ilustra esse processo:
let homeAccountId = null; // Initialize global accountId (can also be localAccountId or username) used for account lookup later, ideally stored in app state
// This callback is passed into `acquireTokenPopup` and `acquireTokenRedirect` to handle the interactive auth response
function handleResponse(resp) {
if (resp !== null) {
homeAccountId = resp.account.homeAccountId; // alternatively: resp.account.homeAccountId or resp.account.username
} else {
const currentAccounts = myMSALObj.getAllAccounts();
if (currentAccounts.length < 1) { // No cached accounts
return;
} else if (currentAccounts.length > 1) { // Multiple account scenario
// Add account selection logic here
} else if (currentAccounts.length === 1) {
homeAccountId = currentAccounts[0].homeAccountId; // Single account scenario
}
}
}
Para saber mais, confira: Contas na MSAL.js
Usar as bibliotecas de wrappers
Se você está desenvolvendo para estruturas Angular e React, é possível usar o MSAL Angular v2 e o MSAL React, respectivamente. Esses wrappers expõem a mesma API pública da MSAL.js, oferecendo métodos e componentes específicos da estrutura que podem agilizar os processos de autenticação e aquisição de tokens.
Executar o aplicativo
Depois que as alterações forem feitas, execute o aplicativo e teste seu cenário de autenticação:
npm start
Exemplo: protegendo um SPA com ADAL.js versus MSAL.js
Os snippets abaixo demonstram o código mínimo necessário para que um aplicativo de página única autentique usuários com a plataforma de identidade da Microsoft e obtenha um token de acesso para o Microsoft Graph usando primeiro a ADAL.js e, em seguida, a MSAL.js:
Usando a ADAL.js | Usando a MSAL.js |
|
|