Tokenopslag in de cache in MSAL Node

Wanneer MSAL Node een token verkrijgt, wordt het in het geheugen opgeslagen voor toekomstig gebruik. MSAL Node beheert de levensduur van het token en vernieuwt het voor u. API's zoals acquireTokenSilent() het ophalen van toegangstokens uit de cache voor een bepaald account:

MSAL stelt om beveiligingsredenen geen vernieuwingstokens beschikbaar. Raadpleeg de veelgestelde vragen over het ophalen van de vernieuwingstokens.

Clientgeheimen veilig gebruiken

Clientgeheimen mogen nooit hardcoded worden. Het dotenv npm-pakket kan worden gebruikt voor het opslaan van geheimen in een .env-bestand (in de hoofdmap van het project) dat moet worden opgenomen in .gitignore om onbedoelde uploads van de geheimen te voorkomen.

const msal = require('@azure/msal-node');
require('dotenv').config(); // process.env now has the values defined in a .env file

// Create msal application object
const cca = new msal.ConfidentialClientApplication({
    auth: {
        clientId: "Enter_the_Application_Id_Here", // e.g. "00001111-aaaa-2222-bbbb-3333cccc4444" (guid)
        authority: "https://login.microsoftonline.com/Enter_the_Tenant_Info_Here", // e.g. "common" or your tenantId (guid)
        clientSecret: process.env.clientSecret // obtained during app registration
    }
});

/**
* acquireToken* APIs return an account object containing the "homeAccountId"
* you should keep a record of this in your app and use it later on when calling acquireTokenSilent
*/
const someUserHomeAccountId = "Enter_User_Home_Account_Id";

const msalTokenCache = cca.getTokenCache();
const account = await msalTokenCache.getAccountByHomeId(someUserHomeAccountId);

const silentTokenRequest = {
    account: account,
    scopes: ["User.Read"],
};

cca.acquireTokenSilent(silentTokenRequest).then((response) => {
    // do something with response
}).catch((error) => {
    // catch and handle errors
});

In productie wilt u waarschijnlijk de tokencache serialiseren en behouden. Afhankelijk van het type toepassing kunt u het volgende doen:

  • Desktop-apps, consoletoepassingen (openbare clienttoepassingen (PCA)):
    • Gebruik MSAL Node Extensions, dat oplossingen biedt voor persistentie en versleuteling van gegevens in rust op Windows, Linux en Mac OS
  • web-apps, web-API’s, daemon-apps (vertrouwelijke-clienttoepassingen (CCA)):
    • De token-cache in het geheugen van MSAL is niet schaalbaar voor productie. Gebruik het patroon voor gedistribueerde tokencaching om de cache in uw keuze aan opslagomgeving (Redis, MongoDB, SQL-databases, enzovoort) te behouden -keep in gedachten dat u deze samen kunt gebruiken , bijvoorbeeld een Redis-achtige geheugencache als eerste laag van persistentie en een SQL-database als een tweede, stabielere persistentielaag)

Cache in het geheugen

MSAL onderhoudt een cache in het geheugen. De cache in het geheugen is representatief voor de status van de toepassingscache. De levensduur van cache in het geheugen is hetzelfde als het MSAL-toepassingsobject. Als het proces dat MSAL gebruikt opnieuw wordt gestart, wordt de cache gewist wanneer de levenscyclus van het proces is voltooid. Als de cache in het geheugen leeg is en er geen permanente cache is om de cache te herstellen, moeten gebruikers zich opnieuw verifiëren. Als dit gebeurt, kunnen ze, als de gebruiker nog steeds een actieve sessie met Microsoft Entra ID heeft, opnieuw verifiëren zonder prompts, maar dit verslechtert de gebruikerservaring nog steeds. Service-naar-servicescenario’s (d.w.z. clientreferentiestroom, on-behalf-of-stroom) vormen ook een probleem, omdat het ophalen van een token bij Microsoft Entra ID HTTP-verzoeken vereist en veel trager is dan het ophalen van een token uit de cache.

Houd er rekening mee dat de cache in het geheugen niet schaalbaar is voor toepassingen aan de serverzijde en dat de prestaties afnemen na het bewaren van een paar 100 tokens in de cache. Voor web-app- en web-API-scenario's is dit ongeveer een paar 100 gebruikers. Voor daemon-app-scenario's waarbij clientreferenties worden verleend om andere apps aan te roepen, betekent dit een paar 100 tenants. Zie de onderstaande prestaties voor meer informatie.

⚠• We raden u aan de cache met versleuteling voor alle productietoepassingen te behouden voor zowel de beveiliging als de gewenste levensduur van de cache. Als u ervoor kiest om de cache niet te behouden, is de TokenCache-interface nog steeds beschikbaar voor toegang tot de entiteiten in de cache.

Permanente cache

MSAL Node treedt op wanneer de cache in het geheugen wordt geopend en apps kunnen kiezen of de cache moet worden behouden (zie: TokenCacheContext) (bijvoorbeeld naar een bestand, een SQL-database en enzovoort). Dit bestaat uit twee acties:

  1. Laad de cache van persistentie naar het geheugen van MSAL voordat u de cache opent
  2. Als de cache in het geheugen sinds de laatste toegang is gewijzigd, slaat u de cache weer op in persistentie

Voor het behouden van de cache accepteert MSAL een aangepaste cache-invoegtoepassing in de configuratie. Deze invoegtoepassing moet de ICachePlugin-interface implementeren:

interface ICachePlugin {
    beforeCacheAccess: (tokenCacheContext: TokenCacheContext) => Promise<void>;
    afterCacheAccess: (tokenCacheContext: TokenCacheContext) => Promise<void>;
}

Een eenvoudige implementatie van ICachePlugin de interface kan er als volgt uitzien (zie ook prestaties en beveiliging als u een app aan de serverzijde bouwt):

class MyCachePlugin implements ICachePlugin {
    private client: ICacheClient;

    constructor(client: ICacheClient) {
        this.client = client; // client object to access the persistent cache
    }

    public async beforeCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
        const cacheData = await this.client.get(); // get the cache from persistence
        cacheContext.tokenCache.deserialize(cacheData); // deserialize it to in-memory cache
    }

    public async afterCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
        if (cacheContext.cacheHasChanged) {
            await this.client.set(cacheContext.tokenCache.serialize()); // deserialize in-memory cache to persistence
        }
    }
}
  • Als u een openbare client-app ontwikkelt, verwerken MSAL Node Extensions dit voor u.
  • Als u een vertrouwelijke client-app ontwikkelt, moet u de cache behouden via een afzonderlijke service, omdat één exemplaar van de cache per server niet geschikt is voor een cloudomgeving met veel servers en app-exemplaren.

We raden u ten zeerste aan om de tokencache te versleutelen wanneer deze op schijf wordt bewaard. Voor openbare client-apps wordt dit standaard meegeleverd bij MSAL Node-extensies. Voor vertrouwelijke clients bent u echter verantwoordelijk voor het ontwerpen van een geschikte versleutelingsoplossing.

Prestaties en beveiliging

In openbare client-apps zorgt MSAL Node Extensions voor prestaties en beveiliging voor u.

Voor vertrouwelijke client-apps die gebruikers verwerken (web-apps die gebruikers aanmelden en web-API's aanroepen, en web-API's die downstream-web-API's aanroepen), kunnen er veel gebruikers gelijktijdig actief zijn voor een bepaalde toepassing. Onze aanbeveling is om één cache-blob (zie CacheRecord) per gebruiker te serialiseren. Dit zou helpen bij het schalen van de cache in een gedistribueerd systeem. Gebruik een sleutel voor het partitioneren van de cache (bijvoorbeeldpartitiesleutel), zoals:

  • Voor web-apps: <userObjectId>.<tenantId> (bijvoorbeeld homeAccountId)
  • Voor daemon-apps met meerdere tenants waarvoor clientreferenties worden verleend: <clientId>.<tenantId>
  • Voor web-API's die andere web-API's aanroepen met behulp van OBO: hash van het binnenkomende toegangstoken (d.w.w.v. oboAssertion) -the token dat vervolgens wordt uitgewisseld voor een OBO-token

⚠• Zorg ervoor dat u de prestaties ziet voor meer informatie over het bewaken van het gebruik en het voorkomen van slechte prestaties.

Web-apps

Omdat web-apps gebruikersgericht zijn en vaak afhankelijk zijn van sessies om elke gebruiker bij te houden, wordt de juiste partitiesleutel voor caching vaak opgeslagen in de sessiegegevens en moet deze worden opgehaald voordat de cachezoekactie kan plaatsvinden. Om dit te helpen, biedt MSAL Node de klasse DistributedCachePlugin , waarmee de ICachePlugin wordt geïmplementeerd. Een exemplaar van DistributedCachePlugin vereist:

  • een clientinterface (ICacheClient) waarmee get- en set-bewerkingen op de persistentieserver (Redis, MySQL, enz.) worden uitgevoerd.
  • een partitiebeheer (IPartitionManager), voor het lezen van en schrijven naar cache met betrekking tot een bepaalde sessie-id.

Raadpleeg de web-app met behulp van DistributedCachePlugin voor een voorbeeld-implementatie.

Zie ook

Zie de onderstaande voorbeelden voor meer informatie over het afhandelen van caching in MSAL Node-apps: