Node.js-alkalmazás migrálása ADAL-ból MSAL-be

A Microsoft Authentication Library for Node (MSAL Node) mostantól az ajánlott SDK az Microsoft Identitásplatform regisztrált alkalmazások hitelesítésének és engedélyezésének engedélyezéséhez. Ez a cikk azokat a fontos lépéseket ismerteti, amelyeken át kell mennie ahhoz, hogy az alkalmazásokat áttelepíthesse az Active Directory Authentication Library for Node -ról (ADAL-csomópont) az MSAL-csomópontra.

Előfeltételek

  • Csomópont 10-es, 12-es, 14-es, 16-os vagy 18-os verziója. A verziótámogatás megjegyzésének megtekintése

Alkalmazásregisztrációs beállítások frissítése

Az ADAL-csomópont használatakor valószínűleg az Azure AD 1.0-s végpontot használta. Az ADAL-ról MSAL-re migrált alkalmazásoknak az Azure AD 2.0-s végpontra kell váltaniuk.

MSAL telepítése és importálása

  1. telepítse az MSAL Node-csomagot npm-en keresztül:
  npm install @azure/msal-node
  1. Ezután importálja az MSAL-csomópontot a kódba:
  const msal = require('@azure/msal-node');
  1. Végül távolítsa el az ADAL Node-csomagot, és távolítsa el a kódban lévő hivatkozásokat:
  npm uninstall adal-node

MSAL inicializálása

Az ADAL-csomópontban inicializál egy AuthenticationContext objektumot, amely ezután elérhetővé teszi a különböző hitelesítési folyamatokban (például acquireTokenWithAuthorizationCode webalkalmazásokban) használható metódusokat. Inicializáláskor az egyetlen kötelező paraméter a szolgáltatói URI:

var adal = require('adal-node');

var authorityURI = "https://login.microsoftonline.com/common";
var authenticationContex = new adal.AuthenticationContext(authorityURI);

Az MSAL-csomópontban ehelyett két alternatíva áll rendelkezésére: Ha mobilalkalmazást vagy asztali alkalmazást készít, egy objektumot példányosít PublicClientApplication . A konstruktor olyan konfigurációs objektumot vár, amely legalább a clientId paramétert tartalmazza. Az MSAL alapértelmezés szerint a szolgáltató URI-ját https://login.microsoftonline.com/common adja meg, ha nem adja meg.

const msal = require('@azure/msal-node');

const pca = new msal.PublicClientApplication({
        auth: {
            clientId: "YOUR_CLIENT_ID"
        }
    });

Megjegyzés:

Ha a szolgáltatót a https://login.microsoftonline.com/common 2.0-s verzióban használja, engedélyezi a felhasználóknak, hogy bármilyen Microsoft Entra-szervezettel vagy személyes Microsoft-fiókkal (MSA) jelentkezzenek be. Ha az MSAL-csomópontban korlátozni szeretné a bejelentkezést bármely Microsoft Entra-fiókra (ugyanazzal a viselkedéssel, mint az ADAL-csomóponttal), használja https://login.microsoftonline.com/organizations inkább.

Ha viszont webalkalmazást vagy démonalkalmazást készít, példányosít egy objektumot ConfidentialClientApplication . Az ilyen alkalmazások esetében meg kell adnia egy ügyfél hitelesítő adatait is, például egy titkos ügyfélkulcsot vagy egy tanúsítványt:

const msal = require('@azure/msal-node');

const cca = new msal.ConfidentialClientApplication({
        auth: {
            clientId: "YOUR_CLIENT_ID",
            clientSecret: "YOUR_CLIENT_SECRET"
        }
    });

ConfidentialClientApplicationAz ADAL-tól AuthenticationContexteltérően mindkettő PublicClientApplication ügyfél-azonosítóhoz van kötve. Ez azt jelenti, hogy ha különböző ügyfélazonosítókkal rendelkezik, amelyeket használni szeretne az alkalmazásban, mindegyikhez új MSAL-példányt kell létrehoznia. További információ: MSAL-csomópont inicializálása

MSAL konfigurálása

Ha Microsoft Identitásplatform készít alkalmazásokat, az alkalmazás számos, a hitelesítéshez kapcsolódó paramétert fog tartalmazni. Az ADAL-csomópontban az AuthenticationContext objektum korlátozott számú konfigurációs paraméterrel rendelkezik, amelyekkel példányosíthatja, míg a többi paraméter szabadon lefagy a kódban (például 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: Jogkivonat-szolgáltatót azonosító URL-cím
  • validateAuthority: olyan funkció, amely megakadályozza, hogy a kód jogkivonatokat kérjen egy potenciálisan rosszindulatú szolgáltatótól
  • cache: beállítja az AuthenticationContext-példány által használt jogkivonat-gyorsítótárat. Ha ez a paraméter nincs beállítva, akkor a rendszer egy alapértelmezett memória-gyorsítótárat használ

Az MSAL-csomópont viszont konfiguráció típusú konfigurációs objektumot használ. A következő tulajdonságokat tartalmazza:

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

Jelentős különbség, hogy az MSAL nem rendelkezik a hatóság érvényesítésének letiltására alkalmas jelzővel, és a hatóságok alapértelmezés szerint mindig érvényesítve vannak. Az MSAL összehasonlítja a kért szolgáltatót a Microsoft által ismert hatóságok listájával vagy a konfigurációban megadott hatóságok listájával. További információ: Konfigurációs beállítások

Váltás MSAL API-ra

Az ADAL-csomópont legtöbb nyilvános metódusa egyenértékű az MSAL-csomópontban:

ADAL MSAL Jegyzetek
acquireToken acquireTokenSilent Átnevezve, és most egy fiókobjektumot vár
acquireTokenWithAuthorizationCode acquireTokenByCode
acquireTokenWithClientCredentials acquireTokenByClientCredential
acquireTokenWithRefreshToken acquireTokenByRefreshToken Hasznos érvényes frissítési jogkivonatok áttelepítéséhez
acquireTokenWithDeviceCode acquireTokenByDeviceCode Most kivonatolja a felhasználói kód beszerzését (lásd alább)
acquireTokenWithUsernamePassword acquireTokenByUsernamePassword

Az ADAL-csomópont egyes metódusai azonban elavultak, míg az MSAL-csomópont új metódusokat kínál:

ADAL MSAL Jegyzetek
acquireUserCode N/A Egyesítve ( acquireTokeByDeviceCode lásd fent)
N/A acquireTokenOnBehalfOf Az OBO-folyamatot absztrakciós új módszer
acquireTokenWithClientCertificate N/A Már nincs szükség tanúsítványok hozzárendelésre az inicializálás során (lásd a konfigurációs beállításokat)
N/A getAuthCodeUrl Egy új módszer, amely absztrakciókkal engedélyezi a végpont URL-felépítését

Hatókörök használata erőforrások helyett

Az 1.0-s és a 2.0-s verziójú végpontok közötti fontos különbség az erőforrások elérésének módjával kapcsolatos. Az ADAL-csomópontban először regisztrálnia kell egy engedélyt az alkalmazásregisztrációs portálon, majd hozzáférési jogkivonatot kell kérnie egy erőforráshoz (például a Microsoft Graphhoz) az alábbiak szerint:

authenticationContext.acquireTokenWithAuthorizationCode(
    req.query.code,
    redirectUri,
    resource, // e.g. 'https://graph.microsoft.com'
    clientId,
    clientSecret,
    function (err, response) {
        // do something with the authentication response
    }
);

Az MSAL-csomópont csak a 2.0-s verziójú végpontot támogatja. A 2.0-s verziójú végpont hatókör-központú modellt alkalmaz az erőforrások eléréséhez. Így amikor hozzáférési jogkivonatot kér egy erőforráshoz, meg kell adnia az erőforrás hatókörét is:

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);
});

A hatókör-központú modell egyik előnye a dinamikus hatókörök használatának képessége. Az 1.0-s verziót használó alkalmazások létrehozásakor regisztrálnia kellett az alkalmazás által megkövetelt összes engedélyt (úgynevezett statikus hatókört), hogy a felhasználó hozzájáruljon a bejelentkezéshez. A 2.0-s verzióban a hatókör paraméterrel kérheti le az engedélyeket a kívánt időpontban (tehát dinamikus hatókörök). Ez lehetővé teszi, hogy a felhasználó növekményes hozzájárulást adjon a hatókörökhöz. Ha tehát az elején csak azt szeretné, hogy a felhasználó jelentkezzen be az alkalmazásba, és nincs szüksége semmilyen hozzáférésre, megteheti. Ha később szüksége van a felhasználó naptárának olvasására, akkor kérheti a naptár hatókörét a acquireToken metódusokban, és lekérheti a felhasználó hozzájárulását. További információ: Erőforrások és hatókörök

Ígéretek használata visszahívások helyett

Az ADAL-csomópontban a rendszer visszahívásokat használ minden művelethez, miután a hitelesítés sikeres volt, és a rendszer választ kapott:

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
    }
});

Az MSAL-csomópontban az ígéretek a következők:

    const cca = new msal.ConfidentialClientApplication(msalConfig);

    cca.acquireTokenByClientCredential(tokenRequest).then((response) => {
        // do something with the authentication response
    }).catch((error) => {
        console.log(error);
    });

Az ES8-hoz kapcsolódó aszinkron/várakozási szintaxist is használhatja:

    try {
        const authResponse = await cca.acquireTokenByCode(tokenRequest);
    } catch (error) {
        console.log(error);
    }

Naplózás engedélyezése

Az ADAL-csomópontban a naplózást a kód bármely helyére külön konfigurálhatja:

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.
});

Az MSAL-csomópontban a naplózás a konfigurációs beállítások része, és az MSAL-csomópontpéldány inicializálásával jön létre:

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

Jogkivonat gyorsítótárazásának engedélyezése

Az ADAL-csomópontban lehetősége volt importálni egy memóriabeli tokengyorsítótárat. A jogkivonat-gyorsítótár paraméterként használatos egy AuthenticationContext objektum inicializálásakor:

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

Az MSAL-csomópont alapértelmezés szerint egy memóriabeli tokengyorsítótárat használ. Nem kell explicit módon importálnia; A memóriabeli tokengyorsítótár az osztályok és PublicClientApplication az ConfidentialClientApplication osztályok részeként jelenik meg.

const msalTokenCache = publicClientApplication.getTokenCache();

Fontos, hogy az ADAL-csomóponttal rendelkező korábbi jogkivonat-gyorsítótár nem lesz átvihető az MSAL-csomópontra, mivel a gyorsítótár-sémák nem kompatibilisek. Használhatja azonban azokat az érvényes frissítési jogkivonatokat, amelyeket az alkalmazás korábban az ADAL-csomóponttal szerzett be az MSAL-csomópontban. További információt a frissítési jogkivonatokról szóló szakaszban talál.

A gyorsítótárat saját gyorsítótár beépülő modul megadásával lemezre is írhatja. A gyorsítótár beépülő modulnak implementálnia kell az interfészt ICachePlugin. A naplózáshoz hasonlóan a gyorsítótárazás is része a konfigurációs beállításoknak, és az MSAL-csomópontpéldány inicializálásával jön létre:

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

Egy példa gyorsítótár beépülő modul az alábbiak szerint implementálható:

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
};

Ha nyilvános ügyfélalkalmazásokat fejleszt, például asztali alkalmazásokat, a Csomóponthoz készült Microsoft Authentication Extensions biztonságos mechanizmusokat kínál az ügyfélalkalmazásoknak a platformfüggetlen jogkivonat-gyorsítótár szerializálásához és megőrzéséhez. A támogatott platformok a Windows, a Mac és a Linux.

Megjegyzés:

A Csomóponthozkészült Microsoft Authentication-bővítmények nem ajánlottak webalkalmazásokhoz, mivel skálázási és teljesítménybeli problémákhoz vezethetnek. Ehelyett a webalkalmazásoknak ajánlott a gyorsítótár munkamenetben való megőrzése.

A frissítési jogkivonatokkal kapcsolatos logika eltávolítása

Az ADAL-csomópontban a frissítési jogkivonatok (RT) elérhetővé lettek téve, így a gyorsítótárazással és a acquireTokenWithRefreshToken metódus használatával megoldásokat fejleszthet a jogkivonatok használatára. Tipikus forgatókönyvek, ahol az RT-k különösen relevánsak:

  • Hosszú ideig futó szolgáltatások, amelyek műveleteket hajtanak végre, beleértve az irányítópultok frissítését azon felhasználók nevében, ahol a felhasználók már nem csatlakoznak.
  • WebFarm-forgatókönyvek, amelyek lehetővé teszik az ügyfél számára az RT webszolgáltatáshoz való eljuttatását (a gyorsítótárazás ügyféloldali, titkosított cookie- és nem kiszolgálóoldali).

Az MSAL-csomópont és más MSAL-ek biztonsági okokból nem teszik közzé a frissítési jogkivonatokat. Ehelyett az MSAL kezeli a frissítő jogkivonatokat. Így már nem kell logikát létrehoznia ehhez. Azonban használhatja a korábban beszerzett (és még érvényes) frissítési jogkivonatokat az ADAL-csomópont gyorsítótárából, hogy új jogkivonatokat szerezzen be az MSAL-csomóponttal. Ehhez az MSAL Node az ADAL Node metódusával acquireTokenWithRefreshToken egyenértékű ajánlatokat kínálacquireTokenByRefreshToken:

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);
});

További információt az ADAL-csomópont MSAL-csomópont migrálási mintájában talál.

Megjegyzés:

Javasoljuk, hogy a még érvényes frissítési jogkivonatok használata után az MSAL-csomópont metódusával megsemmisítse a régebbi ADAL-csomópont jogkivonat-gyorsítótárát acquireTokenByRefreshToken .

Hibák és kivételek kezelése

Az MSAL-csomópont használatakor a leggyakoribb hibatípus a interaction_required hiba. Ezt a hibát gyakran egy interaktív jogkivonat-beszerzési kérés kezdeményezésével oldják meg. Ha például gyorsítótárazott frissítési jogkivonatokat használ acquireTokenSilent, az MSAL-csomópont nem fogja tudni csendesen beszerezni a hozzáférési jogkivonatot. Hasonlóképpen előfordulhat, hogy a elérni kívánt webes API feltételes hozzáférési szabályzattal rendelkezik, amely megköveteli, hogy a felhasználó többtényezős hitelesítést (MFA) végezzen. Ilyen esetekben a hiba aktiválással acquireTokenByCode történő kezelése interaction_required az MFA megadását kéri a felhasználótól, lehetővé téve számukra a teljes beszűkítést.

Egy másik gyakori hiba consent_required, amely akkor fordulhat elő, ha a felhasználó nem engedélyezi a védett erőforrások hozzáférési jogkivonatának beszerzéséhez szükséges engedélyeket. interaction_requiredA hiba megoldásához consent_required hasonlóan gyakran kezdeményez egy interaktív jogkivonat-beszerzési kérést a acquireTokenByCode metódus használatával.

Az alkalmazás futtatása

A módosítások végrehajtása után futtassa az alkalmazást, és tesztelje a hitelesítési forgatókönyvet:

npm start

Példa: Jogkivonatok beszerzése az ADAL-csomóponttal és az MSAL-csomóponttal

Az alábbi kódrészlet egy bizalmas ügyfél webalkalmazást mutat be az Express.js keretrendszerben. Bejelentkezést hajt végre, amikor egy felhasználó eléri a hitelesítési útvonalat /auth, beolvas egy hozzáférési jogkivonatot a Microsoft Graphhoz az /redirect útvonalon keresztül, majd megjeleníti az említett jogkivonat tartalmát.

Az ADAL-csomópont használata MSAL-csomópont használata
// Import dependencies
var express = require('express');
var crypto = require('crypto');
var adal = require('adal-node');

// Authentication parameters
var clientId = 'Enter_the_Application_Id_Here';
var clientSecret = 'Enter_the_Client_Secret_Here';
var tenant = 'Enter_the_Tenant_Info_Here';
var authorityUrl = 'https://login.microsoftonline.com/' + tenant;
var redirectUri = 'http://localhost:3000/redirect';
var resource = 'https://graph.microsoft.com';

// Configure logging
adal.Logging.setLoggingOptions({
    log: function (level, message, error) {
        console.log(message);
    },
    level: adal.Logging.LOGGING_LEVEL.VERBOSE,
    loggingWithPII: false
});

// Auth code request URL template
var templateAuthzUrl = 'https://login.microsoftonline.com/'
    + tenant + '/oauth2/authorize?response_type=code&client_id='
    + clientId + '&redirect_uri=' + redirectUri
    + '&state=<state>&resource=' + resource;

// Initialize express
var app = express();

// State variable persists throughout the app lifetime
app.locals.state = "";

app.get('/auth', function(req, res) {

    // Create a random string to use against XSRF
    crypto.randomBytes(48, function(ex, buf) {
        app.locals.state = buf.toString('base64')
            .replace(/\//g, '_')
            .replace(/\+/g, '-');

        // Construct auth code request URL
        var authorizationUrl = templateAuthzUrl
            .replace('<state>', app.locals.state);

        res.redirect(authorizationUrl);
    });
});

app.get('/redirect', function(req, res) {
    // Compare state parameter against XSRF
    if (app.locals.state !== req.query.state) {
        res.send('error: state does not match');
    }

    // Initialize an AuthenticationContext object
    var authenticationContext =
        new adal.AuthenticationContext(authorityUrl);

    // Exchange auth code for tokens
    authenticationContext.acquireTokenWithAuthorizationCode(
        req.query.code,
        redirectUri,
        resource,
        clientId,
        clientSecret,
        function(err, response) {
            res.send(response);
        }
    );
});

app.listen(3000, function() {
    console.log(`listening on port 3000!`);
});
// Import dependencies
const express = require("express");
const msal = require('@azure/msal-node');

// Authentication parameters
const config = {
    auth: {
        clientId: "Enter_the_Application_Id_Here",
        authority: "https://login.microsoftonline.com/Enter_the_Tenant_Info_Here",
        clientSecret: "Enter_the_Client_Secret_Here"
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: msal.LogLevel.Verbose,
        }
    }
};

const REDIRECT_URI = "http://localhost:3000/redirect";

// Initialize MSAL Node object using authentication parameters
const cca = new msal.ConfidentialClientApplication(config);

// Initialize express
const app = express();

app.get('/auth', (req, res) => {

    // Construct a request object for auth code
    const authCodeUrlParameters = {
        scopes: ["user.read"],
        redirectUri: REDIRECT_URI,
    };

    // Request auth code, then redirect
    cca.getAuthCodeUrl(authCodeUrlParameters)
        .then((response) => {
            res.redirect(response);
        }).catch((error) => res.send(error));
});

app.get('/redirect', (req, res) => {

    // Use the auth code in redirect request to construct
    // a token request object
    const tokenRequest = {
        code: req.query.code,
        scopes: ["user.read"],
        redirectUri: REDIRECT_URI,
    };

    // Exchange the auth code for tokens
    cca.acquireTokenByCode(tokenRequest)
        .then((response) => {
            res.send(response);
        }).catch((error) => res.status(500).send(error));
});

app.listen(3000, () =>
    console.log(`listening on port 3000!`));

További lépések