Come eseguire la migrazione di un'app Node.js da ADAL a MSAL
Microsoft Authentication Library per Node (nodo MSAL) è ora l'SDK consigliato per abilitare l'autenticazione e l'autorizzazione per le applicazioni registrate in Microsoft Identity Platform. Questo articolo illustra i passaggi importanti da eseguire per eseguire la migrazione delle app da Active Directory Authentication Library per node (nodo ADAL) al nodo MSAL.
Prerequisiti
- Nodo versione 10, 12, 14, 16 o 18. Vedere la nota sul supporto della versione
Aggiornare le impostazioni di registrazione dell'app
Quando si usa ad ADAL Node, è probabile che si usi l'endpoint di Azure AD v1.0. Le app che eseguono la migrazione da ADAL a MSAL devono passare all'endpoint di Azure AD v2.0.
Installare e importare MSAL
- installare il pacchetto node MSAL tramite npm:
npm install @azure/msal-node
- Successivamente, importare il nodo MSAL nel codice:
const msal = require('@azure/msal-node');
- Infine, disinstallare il pacchetto ADAL Node e rimuovere eventuali riferimenti nel codice:
npm uninstall adal-node
Inizializzare MSAL
Nel nodo ADAL si inizializza un AuthenticationContext
oggetto che espone quindi i metodi che è possibile usare in flussi di autenticazione diversi, acquireTokenWithAuthorizationCode
ad esempio per le app Web. Durante l'inizializzazione, l'unico parametro obbligatorio è l'URI dell'autorità:
var adal = require('adal-node');
var authorityURI = "https://login.microsoftonline.com/common";
var authenticationContex = new adal.AuthenticationContext(authorityURI);
Nel nodo MSAL sono invece disponibili due alternative: se si sta creando un'app per dispositivi mobili o un'app desktop, si crea un'istanza di un PublicClientApplication
oggetto . Il costruttore prevede un oggetto di configurazione che contiene almeno il clientId
parametro . MSAL imposta per impostazione predefinita l'URI https://login.microsoftonline.com/common
dell'autorità su se non viene specificato.
const msal = require('@azure/msal-node');
const pca = new msal.PublicClientApplication({
auth: {
clientId: "YOUR_CLIENT_ID"
}
});
Nota
Se si usa l'autorità https://login.microsoftonline.com/common
nella versione 2.0, si consentirà agli utenti di accedere con qualsiasi organizzazione Microsoft Entra o con un account Microsoft personale . Nel nodo MSAL, se si vuole limitare l'accesso a qualsiasi account Microsoft Entra (stesso comportamento di quello di ADAL Node), usare https://login.microsoftonline.com/organizations
invece .
D'altra parte, se si sta creando un'app Web o un'app daemon, si crea un'istanza di un ConfidentialClientApplication
oggetto . Con tali app è anche necessario fornire credenziali client, ad esempio un segreto client o un certificato:
const msal = require('@azure/msal-node');
const cca = new msal.ConfidentialClientApplication({
auth: {
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET"
}
});
Sia PublicClientApplication
che ConfidentialClientApplication
, a differenza di AuthenticationContext
ADAL, è associato a un ID client. Ciò significa che se si dispone di ID client diversi che si desidera usare nell'applicazione, è necessario creare un'istanza di MSAL nuova per ogni istanza. Per altre informazioni, vedere Inizializzazione del nodo MSAL
Configurare MSAL
Quando si creano app in Microsoft Identity Platform, l'app conterrà molti parametri correlati all'autenticazione. Nel nodo ADAL l'oggetto AuthenticationContext
ha un numero limitato di parametri di configurazione con cui è possibile crearne un'istanza, mentre i parametri rimanenti si bloccano liberamente nel codice, ad esempio clientSecret:
var adal = require('adal-node');
var authority = "https://login.microsoftonline.com/YOUR_TENANT_ID"
var validateAuthority = true,
var cache = null;
var authenticationContext = new adal.AuthenticationContext(authority, validateAuthority, cache);
authority
: URL che identifica un'autorità di tokenvalidateAuthority
: funzionalità che impedisce al codice di richiedere token da un'autorità potenzialmente dannosacache
: imposta la cache dei token usata da questa istanza authenticationContext. Se questo parametro non è impostato, viene usato un valore predefinito nella cache di memoria
Il nodo MSAL usa invece un oggetto di configurazione di tipo Configuration. Contiene le seguenti proprietà:
const msal = require('@azure/msal-node');
const msalConfig = {
auth: {
clientId: "YOUR_CLIENT_ID",
authority: "https://login.microsoftonline.com/YOUR_TENANT_ID",
clientSecret: "YOUR_CLIENT_SECRET",
knownAuthorities: [],
},
cache: {
// your implementation of caching
},
system: {
loggerOptions: { /** logging related options */ }
}
}
const cca = new msal.ConfidentialClientApplication(msalConfig);
Come differenza notevole, MSAL non ha un flag per disabilitare la convalida dell'autorità e le autorità vengono sempre convalidate per impostazione predefinita. MSAL confronta l'autorità richiesta con un elenco di autorità note a Microsoft o a un elenco di autorità specificate nella configurazione. Per altre informazioni, vedere Opzioni di configurazione
Passare all'API MSAL
La maggior parte dei metodi pubblici nel nodo ADAL ha equivalenti nel nodo MSAL:
ADAL | MSAL | Note |
---|---|---|
acquireToken |
acquireTokenSilent |
Rinominato e ora prevede un oggetto account |
acquireTokenWithAuthorizationCode |
acquireTokenByCode |
|
acquireTokenWithClientCredentials |
acquireTokenByClientCredential |
|
acquireTokenWithRefreshToken |
acquireTokenByRefreshToken |
Utile per la migrazione di token di aggiornamento validi |
acquireTokenWithDeviceCode |
acquireTokenByDeviceCode |
Ora astrae l'acquisizione del codice utente (vedere di seguito) |
acquireTokenWithUsernamePassword |
acquireTokenByUsernamePassword |
Tuttavia, alcuni metodi nel nodo ADAL sono deprecati, mentre il nodo MSAL offre nuovi metodi:
ADAL | MSAL | Note |
---|---|---|
acquireUserCode |
N/D | Uniti con acquireTokeByDeviceCode (vedere sopra) |
N/D | acquireTokenOnBehalfOf |
Nuovo metodo che astrae il flusso OBO |
acquireTokenWithClientCertificate |
N/D | Non più necessario perché i certificati vengono assegnati durante l'inizializzazione ora (vedere le opzioni di configurazione) |
N/D | getAuthCodeUrl |
Nuovo metodo che astrae la costruzione dell'URL dell'endpoint |
Usare ambiti anziché risorse
Una differenza importante tra gli endpoint v1.0 e v2.0 riguarda la modalità di accesso alle risorse. Nel nodo ADAL è prima necessario registrare un'autorizzazione nel portale di registrazione delle app e quindi richiedere un token di accesso per una risorsa, ad esempio Microsoft Graph, come illustrato di seguito:
authenticationContext.acquireTokenWithAuthorizationCode(
req.query.code,
redirectUri,
resource, // e.g. 'https://graph.microsoft.com'
clientId,
clientSecret,
function (err, response) {
// do something with the authentication response
}
);
Il nodo MSAL supporta solo l'endpoint 2.0 . L'endpoint v2.0 usa un modello incentrato sull'ambito per accedere alle risorse. Pertanto, quando si richiede un token di accesso per una risorsa, è necessario specificare anche l'ambito per tale risorsa:
const tokenRequest = {
code: req.query.code,
scopes: ["https://graph.microsoft.com/User.Read"],
redirectUri: REDIRECT_URI,
};
pca.acquireTokenByCode(tokenRequest).then((response) => {
// do something with the authentication response
}).catch((error) => {
console.log(error);
});
Uno dei vantaggi del modello incentrato sull'ambito è la possibilità di usare ambiti dinamici. Quando si compilano applicazioni con la versione 1.0, è necessario registrare il set completo di autorizzazioni (denominate ambiti statici) richiesti dall'applicazione per consentire all'utente di fornire il consenso al momento dell'accesso. Nella versione 2.0 è possibile usare il parametro di ambito per richiedere le autorizzazioni al momento desiderate (di conseguenza, ambiti dinamici). In questo modo l'utente può fornire il consenso incrementale agli ambiti. Pertanto, se all'inizio si vuole semplicemente che l'utente acceda all'applicazione e non è necessario alcun tipo di accesso, è possibile impostare questo tipo di autorizzazione. Se, in un secondo momento, si vuole avere la possibilità di leggere il calendario dell'utente, è possibile richiedere l'ambito del calendario nei metodi di acquisizione dei token e ottenere il consenso dell'utente. Per altre informazioni, vedere Risorse e ambiti
Usare promesse anziché callback
Nel nodo ADAL i callback vengono usati per qualsiasi operazione dopo che l'autenticazione ha esito positivo e viene ottenuta una risposta:
var context = new AuthenticationContext(authorityUrl, validateAuthority);
context.acquireTokenWithClientCredentials(resource, clientId, clientSecret, function(err, response) {
if (err) {
console.log(err);
} else {
// do something with the authentication response
}
});
Nel nodo MSAL vengono invece usate le promesse:
const cca = new msal.ConfidentialClientApplication(msalConfig);
cca.acquireTokenByClientCredential(tokenRequest).then((response) => {
// do something with the authentication response
}).catch((error) => {
console.log(error);
});
È anche possibile usare la sintassi async/await fornita con ES8:
try {
const authResponse = await cca.acquireTokenByCode(tokenRequest);
} catch (error) {
console.log(error);
}
Abilitazione della registrazione
Nel nodo ADAL configurare la registrazione separatamente in qualsiasi posizione nel codice:
var adal = require('adal-node');
//PII or OII logging disabled. Default Logger does not capture any PII or OII.
adal.logging.setLoggingOptions({
log: function (level, message, error) {
console.log(message);
if (error) {
console.log(error);
}
},
level: logging.LOGGING_LEVEL.VERBOSE, // provide the logging level
loggingWithPII: false // Determine if you want to log personal identification information. The default value is false.
});
Nel nodo MSAL la registrazione fa parte delle opzioni di configurazione e viene creata con l'inizializzazione dell'istanza del nodo MSAL:
const msal = require('@azure/msal-node');
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 cca = new msal.ConfidentialClientApplication(msalConfig);
Abilitare la memorizzazione nella cache dei token
Nel nodo ADAL era possibile importare una cache dei token in memoria. La cache dei token viene usata come parametro durante l'inizializzazione di un AuthenticationContext
oggetto:
var MemoryCache = require('adal-node/lib/memory-cache');
var cache = new MemoryCache();
var authorityURI = "https://login.microsoftonline.com/common";
var context = new AuthenticationContext(authorityURI, true, cache);
Per impostazione predefinita, il nodo MSAL usa una cache dei token in memoria. Non è necessario importarlo in modo esplicito; La cache dei token in memoria viene esposta come parte delle ConfidentialClientApplication
classi e PublicClientApplication
.
const msalTokenCache = publicClientApplication.getTokenCache();
Importante, la cache dei token precedente con il nodo ADAL non sarà trasferiscibile nel nodo MSAL, perché gli schemi della cache non sono compatibili. Tuttavia, puoi usare i token di aggiornamento validi ottenuti in precedenza con il nodo ADAL nel nodo MSAL. Per altre informazioni, vedere la sezione relativa ai token di aggiornamento.
È anche possibile scrivere la cache su disco fornendo il proprio plug-in della cache. Il plug-in cache deve implementare l'interfaccia ICachePlugin
. Analogamente alla registrazione, la memorizzazione nella cache fa parte delle opzioni di configurazione e viene creata con l'inizializzazione dell'istanza del nodo MSAL:
const msal = require('@azure/msal-node');
const msalConfig = {
auth: {
// authentication related parameters
},
cache: {
cachePlugin // your implementation of cache plugin
},
system: {
// logging related options
}
}
const msalInstance = new ConfidentialClientApplication(msalConfig);
Un plug-in cache di esempio può essere implementato come indicato di seguito:
const fs = require('fs');
// Call back APIs which automatically write and read into a .json file - example implementation
const beforeCacheAccess = async (cacheContext) => {
cacheContext.tokenCache.deserialize(await fs.readFile(cachePath, "utf-8"));
};
const afterCacheAccess = async (cacheContext) => {
if(cacheContext.cacheHasChanged) {
await fs.writeFile(cachePath, cacheContext.tokenCache.serialize());
}
};
// Cache Plugin
const cachePlugin = {
beforeCacheAccess,
afterCacheAccess
};
Se si sviluppano applicazioni client pubbliche come app desktop, Microsoft Authentication Extensions for Node offre meccanismi sicuri per le applicazioni client per eseguire la serializzazione e la persistenza della cache dei token multipiattaforma. Le piattaforme supportate sono Windows, Mac e Linux.
Nota
Le estensioni di autenticazione Microsoft per Node non sono consigliate per le applicazioni Web, perché possono causare problemi di scalabilità e prestazioni. Le app Web sono invece consigliate per rendere persistente la cache nella sessione.
Rimuovere la logica per i token di aggiornamento
Nel nodo ADAL i token di aggiornamento (RT) sono stati esposti consentendo di sviluppare soluzioni per l'uso di questi token memorizzandoli nella cache e usando il acquireTokenWithRefreshToken
metodo . Scenari tipici in cui le RT sono particolarmente rilevanti:
- Servizi a esecuzione prolungata che eseguono azioni, inclusi l'aggiornamento dei dashboard per conto degli utenti in cui gli utenti non sono più connessi.
- Scenari WebFarm per consentire al client di portare rt al servizio Web (la memorizzazione nella cache viene eseguita sul lato client, cookie crittografato e non sul lato server).
Il nodo MSAL, insieme ad altri msals, non espone i token di aggiornamento per motivi di sicurezza. MSAL gestisce invece automaticamente i token di aggiornamento. Di conseguenza, non è più necessario compilare la logica per questo. Tuttavia, è possibile usare i token di aggiornamento acquisiti in precedenza (e ancora validi) dalla cache del nodo ADAL per ottenere un nuovo set di token con il nodo MSAL. A tale scopo, il nodo MSAL offre acquireTokenByRefreshToken
, che equivale al metodo del acquireTokenWithRefreshToken
nodo ADAL:
var msal = require('@azure/msal-node');
const config = {
auth: {
clientId: "ENTER_CLIENT_ID",
authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
clientSecret: "ENTER_CLIENT_SECRET"
}
};
const cca = new msal.ConfidentialClientApplication(config);
const refreshTokenRequest = {
refreshToken: "", // your previous refresh token here
scopes: ["https://graph.microsoft.com/.default"],
forceCache: true,
};
cca.acquireTokenByRefreshToken(refreshTokenRequest).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
Per altre informazioni, vedere l'esempio di migrazione del nodo ADAL al nodo MSAL.
Nota
È consigliabile eliminare definitivamente la cache dei token del nodo ADAL precedente quando si usano i token di aggiornamento ancora validi per ottenere un nuovo set di token usando il metodo del acquireTokenByRefreshToken
nodo MSAL, come illustrato in precedenza.
Gestire errori ed eccezioni
Quando si usa il nodo MSAL, il tipo di errore più comune che si potrebbe riscontrare è l'errore interaction_required
. Questo errore viene spesso risolto avviando una richiesta di acquisizione interattiva dei token. Ad esempio, quando si usa acquireTokenSilent
, se non sono presenti token di aggiornamento memorizzati nella cache, il nodo MSAL non sarà in grado di acquisire automaticamente un token di accesso. Analogamente, l'API Web a cui si sta tentando di accedere potrebbe avere un criterio di accesso condizionale, che richiede all'utente di eseguire l'autenticazione a più fattori (MFA). In questi casi, la gestione degli interaction_required
errori attivando acquireTokenByCode
richiederà all'utente l'autenticazione a più fattori, consentendogli di completarla.
Un altro errore comune che potrebbe verificarsi è consent_required
, che si verifica quando le autorizzazioni necessarie per ottenere un token di accesso per una risorsa protetta non vengono concesse dall'utente. Come in interaction_required
, la soluzione per consent_required
l'errore spesso avvia una richiesta di acquisizione interattiva del token, usando il acquireTokenByCode
metodo .
Eseguire l'app
Al termine delle modifiche, eseguire l'app e testare lo scenario di autenticazione:
npm start
Esempio: Acquisizione di token con nodo ADAL e nodo MSAL
Il frammento di codice seguente illustra un'app Web client riservata nel framework Express.js. Esegue un accesso quando un utente raggiunge la route /auth
di autenticazione , acquisisce un token di accesso per Microsoft Graph tramite la /redirect
route e quindi visualizza il contenuto del token specificato.
Uso del nodo ADAL | Uso del nodo MSAL |
|
|