Mise en cache des jetons dans MSAL Node

Lorsque MSAL Node acquiert un jeton, il le met en mémoire pour une utilisation ultérieure. MSAL Node gère la durée de vie des jetons et leur actualisation pour vous. Les API telles que acquireTokenSilent() récupère des jetons d’accès à partir du cache pour un compte donné :

MSAL n’expose pas les jetons d’actualisation pour des raisons de sécurité. Reportez-vous au FAQ pour savoir comment obtenir les jetons d’actualisation.

Utiliser les secrets client en toute sécurité

Les secrets client ne doivent jamais être codés en dur. Le package npm dotenv peut être utilisé pour stocker des secrets dans un fichier .env (situé dans le répertoire racine du projet) qui doit être inclus dans .gitignore pour empêcher les chargements accidentels des secrets.

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

En production, vous souhaiterez très probablement sérialiser et conserver le cache de tokens. Selon le type d’application, vous pouvez :

  • Applications de bureau, applications en console (applications clientes publiques (PCA)) :
  • Applications Web, API Web, applications démon (applications clientes confidentielles (CCA)) :
    • Le cache de tokens en mémoire de MSAL n'est pas adapté à un environnement de production. Utilisez le modèle de mise en cache des jetons distribués pour conserver le cache dans votre choix d’environnement de stockage (Redis, MongoDB, bases de données SQL, etc. -keep à l’esprit que vous pouvez les utiliser en tandem , par exemple , un cache de mémoire redis comme première couche de persistance et une base de données SQL en tant que deuxième couche de persistance plus stable)

Cache en mémoire

MSAL gère un cache en mémoire. Le cache en mémoire est représentatif de l’état du cache d’application. La durée de vie du cache en mémoire est identique à l’objet d’application MSAL. Si le processus utilisant MSAL redémarre, le cache est effacé lorsque le cycle de vie du processus se termine. Si le cache en mémoire est vide et qu’il n’y a pas de cache persistant à partir duquel restaurer le cache, les utilisateurs devront s’authentifier à nouveau. Lorsque cela se produit, si l’utilisateur dispose toujours d’une session active avec Microsoft Entra ID, il se peut qu’il se réauthentifie sans aucune invite, mais l’expérience utilisateur s’en trouve malgré tout dégradée. Les scénarios de service à service (c’est-à-dire le flux des informations d’identification du client et le flux au nom de l’utilisateur) sont également pénalisés, car l’obtention d’un jeton depuis Microsoft Entra ID implique des requêtes HTTP et est bien plus lente que sa récupération depuis le cache.

Notez que le cache en mémoire n’est pas évolutif pour les applications côté serveur et que les performances se dégradent après avoir conservé quelques 100 jetons dans le cache. Pour les scénarios d’application web et d’API web, il s’agit approximativement de servir quelques 100 utilisateurs. Pour les scénarios d'applications démon utilisant l'octroi d'informations d'identification client pour appeler d'autres applications, cela représente quelques centaines de locataires. Pour plus d’informations, consultez les performances ci-dessous.

⚠️ Nous vous recommandons de conserver le cache avec chiffrement pour toutes les applications de production à la fois pour la sécurité et la longévité souhaitée du cache. Si vous choisissez de ne pas conserver le cache, l’interface TokenCache est toujours disponible pour accéder aux entités mises en cache.

Cache persistant

MsAL Node déclenche des événements lorsque le cache en mémoire est accessible et que les applications peuvent choisir de conserver le cache (voir : TokenCacheContext) (par exemple, dans un fichier, une base de données SQL et etc.). Il s’agit de deux actions :

  1. Charger le cache de la persistance vers la mémoire de MSAL avant d’accéder au cache
  2. Si le cache en mémoire a changé depuis le dernier accès, enregistrez le cache dans la persistance

Pour conserver le cache, MSAL accepte un plug-in de cache personnalisé dans la configuration. Ce plug-in doit implémenter l’interface ICachePlugin :

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

Une implémentation de base de l’interface ICachePlugin peut se présenter comme suit (voir également les performances et la sécurité si vous créez une application côté serveur) :

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
        }
    }
}
  • Si vous développez une application cliente publique, msAL Node Extensions gère cela pour vous.
  • Si vous développez une application cliente confidentielle, vous devez conserver le cache via un service distinct, car une seule instance de cache par serveur n’est pas adaptée à un environnement cloud avec de nombreux serveurs et instances d’application.

Nous vous recommandons vivement de chiffrer le cache de jetons lors de sa conservation sur le disque. Pour les applications clientes publiques, cette option est proposée prête à l’emploi avec les extensions de nœud MSAL. Toutefois, pour les clients confidentiels, vous êtes responsable de l’élaboration d’une solution de chiffrement appropriée.

Performances et sécurité

Sur les applications clientes publiques, les extensions de nœud MSAL garantissent les performances et la sécurité pour vous.

Sur les applications clientes confidentielles qui gèrent les utilisateurs (applications web qui connectent des utilisateurs et appellent des API web et des API web appelant des API web en aval), de nombreux utilisateurs peuvent être actifs simultanément pour une application donnée. Nous vous recommandons de sérialiser un objet blob de cache (voir CacheRecord) par utilisateur. Cela permet de mettre à l’échelle le cache sur un système distribué. Utilisez une clé pour partitionner le cache (par exemple, clé de partition), par exemple :

  • Pour les applications web : <userObjectId>.<tenantId> (par exemple homeAccountId)
  • Pour les applications démon multilocataires utilisant l'octroi d'informations d'identification client : <clientId>.<tenantId>
  • Pour les API web appelant d’autres API web à l’aide d’OBO : hachage du jeton d’accès entrant (c.-à-d. oboAssertion) - le jeton qui sera ensuite échangé contre un jeton OBO

⚠️ Veillez à voir les performances pour plus d’informations sur la façon de surveiller l’utilisation et d’éviter les performances médiocres.

les applications web

Étant donné que les applications web sont accessibles à l’utilisateur et s’appuient souvent sur des sessions pour suivre chaque utilisateur, la clé de partition appropriée pour la mise en cache est souvent stockée dans les données de session et doit être récupérée avant que la recherche du cache puisse avoir lieu. Pour vous aider à cela, MSAL Node fournit la classe DistributedCachePlugin , qui implémente ICachePlugin. Une instance de DistributedCachePlugin nécessite :

  • une interface client (ICacheClient), qui implémente les opérations get et set sur le serveur de persistance (Redis, MySQL, etc.).
  • un gestionnaire de partitions (IPartitionManager), pour la lecture et l’écriture dans le cache par rapport à un ID de session donné.

Reportez-vous à l’application web à l’aide de DistributedCachePlugin pour obtenir un exemple d’implémentation.

Voir aussi

Pour plus d’informations sur la gestion de la mise en cache dans les applications MSAL Node, consultez les exemples ci-dessous :