Расширения аутентификации Microsoft для Node.js

Расширения Microsoft Authentication для Node предоставляют безопасные механизмы, которые позволяют клиентским приложениям выполнять межплатформенную сериализацию и постоянное хранение кэша токенов.

MSAL Node требует от разработчиков реализовать собственную логику для сохранения кэша токенов. Расширения MSAL Node предназначены для предоставления надежной, безопасной и настраиваемой реализации постоянного хранилища кэша токенов в Windows, macOS и Linux для публичных клиентских приложений (настольных приложений, приложений CLI и т. д.). Он предоставляет механизмы шифрования, а также доступа к кэшу маркеров несколькими процессами одновременно.

Поддерживаемые платформы Windows, Mac и Linux:

  • Windows — DPAPI используется для шифрования.
  • MAC — MAC KeyChain используется через npm-пакет keytar.
  • Linux — libsecret используется для хранения в службе "Secret Service" с помощью npm-пакета keytar.

Code

Создание слоя персистентности

API для создания уровня сохраняемости будет отличаться в зависимости от того, на какую платформу вы нацелены.

Кроме того, вы можете использовать createPersistence API из PersistenceCreator , так как это универсальная оболочка и выбирает соответствующий метод сохраняемости на основе платформы или ОС.

const { PublicClientApplication } = require("@azure/msal-node");
const {
  DataProtectionScope,
  PersistenceCreator,
  PersistenceCachePlugin,
} = require("@azure/msal-node-extensions");

const persistence = await PersistenceCreator.createPersistence({
                cachePath: "path/to/cache/file.json",
                dataProtectionScope: DataProtectionScope.CurrentUser,
                serviceName: "test-msal-electron-service",
                accountName: "test-msal-electron-account",
                usePlaintextFileOnLinux: false,
          });
// Use the persistence object to initialize an MSAL PublicClientApplication with cachePlugin
const pca = new PublicClientApplication({
                auth: {
                        clientId: "CLIENT_ID_HERE",
                    },
                cache: {
                        cachePlugin: new PersistenceCachePlugin(persistence);
                    },
                });

Кроме того, можно использовать следующие параметры для конкретной платформы:


const { FilePersistenceWithDataProtection, DataProtectionScope } = require("@azure/msal-node-extensions");
const { PublicClientApplication } = require("@azure/msal-node");

const cachePath = "path/to/cache/file.json";
const dataProtectionScope = DataProtectionScope.CurrentUser;
const optionalEntropy = ""; //specifies password or other additional entropy used to encrypt the data.
const windowsPersistence = await FilePersistenceWithDataProtection.create(cachePath, dataProtectionScope, optionalEntropy);
// Use the persistence object to initialize an MSAL PublicClientApplication with cachePlugin
const pca = new PublicClientApplication({
                auth: {
                        clientId: "CLIENT_ID_HERE",
                    },
                cache: {
                        cachePlugin: new PersistenceCachePlugin(windowsPersistence);
                    },
                });

  • cachePath — это путь в файловой системе, в которой будет храниться зашифрованный файл кэша.
  • dataProtectionScope указывает область защиты данных, текущего пользователя или локального компьютера. Вам не нужен ключ для защиты или отмены защиты данных. Если для области задано значение CurrentUser, только приложения, работающие на учетных данных, могут не защитить данные; Однако это означает, что любое приложение, работающее на ваших учетных данных, может получить доступ к защищенным данным. Если задать область действия LocalMachine, любое приложение с полным доверием на компьютере сможет снять защиту, получить доступ к данным и изменить их.
  • optionalEntropy указывает пароль или другую дополнительную энтропию, используемую для шифрования данных.

FilePersistenceWithDataProtection использует API Win32 CryptProtectData и CryptUnprotectData. Дополнительные сведения о dataProtectionScope или optionalEntropy, см. в документации по этим API.

Все платформы

Сохраняемость незашифрованных файлов, которая работает на всех платформах, предоставляется для удобства, хотя и не рекомендуется.

const { FilePersistence } = require("@azure/msal-node-extensions");

const filePath = "path/to/cache/file.json";
const filePersistence = await FilePersistence.create(filePath, loggerOptions);
// Pass the persistence to msal config's cachePlugin
const pca = new PublicClientApplication({
    auth: {
            clientId: "CLIENT_ID_HERE",
        },
    cache: {
            cachePlugin: new PersistenceCachePlugin(filePersistence);
        },
  });

Если файл или каталог не был создан, FilePersistence.create() создадит файл и все каталоги в пути рекурсивно. Это можно увидеть в работе в FilePersistence.ts

Передача параметров блокировки плагину Cache для параллельного выполнения

Создайте PersistenceCachePlugin, передав объект персистентности, созданный на предыдущем шаге.

const { PersistenceCachePlugin } = require("@azure/msal-node-extensions");

const persistenceCachePlugin = new PersistenceCachePlugin(windowsPersistence); // or any of the other ones.

Для поддержки параллельного доступа несколькими процессами расширения используют блокировку на основе файлов. Можно настроить номер повторных попыток и задержку повторных попыток для получения блокировки с помощью CrossPlatformLockOptions.

const {
  PersistenceCreator,
  PersistenceCachePlugin,
} = require("@azure/msal-node-extensions");

const lockOptions = {
    retryNumber: 100,
    retryDelay: 50
}

const persistence = await PersistenceCreator.createPersistence(persistenceConfiguration);
const persistenceCachePlugin = new PersistenceCachePlugin(persistence, lockOptions); // or any of the other ones
const pca = new PublicClientApplication({
    auth: {
            clientId: "CLIENT_ID_HERE",
        },
    cache: {
            cachePlugin: persistenceCachePlugin
        },
    });

Настройка PersistenceCachePlugin в конфигурации MSAL Node PublicClientApplication (с примером)

Подводя итог, когда у вас есть PersistenceCachePlugin, его можно задать в MSAL Node PublicClientApplication, указав его как часть объекта configuration, как показано ниже.

import { PublicClientApplication } from "@azure/msal-node";

const publicClientConfig = {
    auth: {
        clientId: "",
        authority: "",
    },
    cache: {
        cachePlugin: persistenceCachePlugin
    },
};

const pca = new PublicClientApplication(publicClientConfig);

Пример (для настольного приложения на Electron и Node.js):-

authConfig.js:-

const AAD_ENDPOINT_HOST = "https://login.microsoftonline.com/"; // include the trailing slash
const REDIRECT_URI = "ENTER_REDIRECT_URI";

const cachePath = "path/to/cache/file.json";

/*define persistence config based on the appropriate persistence you are using(e.g- FilePersistenceWithDataProtection, generic PersistenceCreateor, etc)*/

//defining persistence config for PersistenceCreator
const persistenceConfiguration = {
    cachePath,
    dataProtectionScope: DataProtectionScope.CurrentUser,
    serviceName: "test-msal-electron-service",
    accountName: "test-msal-electron-account",
    usePlaintextFileOnLinux: false,
}

  const msalConfig = {
    auth: {
        clientId: "CLIENT_ID_HERE",
        authority: `${AAD_ENDPOINT_HOST}TENANT_ID_HERE`,
    },
    cache: {
        cachePlugin: null // set later in main.js as shown above 
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: LogLevel.Verbose,
        },
    },
};
...

module.exports = {
  msalConfig: msalConfig,
  protectedResources: protectedResources,
  REDIRECT_URI: REDIRECT_URI,
  persistenceConfiguration
};

Примечание для разработчиков Electron

Пример для Electron: в этом примере показано, как интегрировать библиотеку msal-node-extensions в приложение Electron, собранное с помощью webpack.

Если вы используете это расширение для Electron, может возникнуть ошибка, аналогичная этой:

Uncaught Exception:
Error: The module
"<path-to-project>\node_modules\...\dpapi.node" was compiled against a different Node.js version using NODE_MODULE_VERSION 85. This version of Node.js requires NODE_MODULE_VERSION 80. Please try re-compiling or re-installing the module...."

Эта ошибка, вероятно, связана с различиями версий Node.js между проектом Electron и расширением. Это можно сделать, повторно создав пакет, выполнив следующие действия.

  • Установите electron-rebuild с помощью команды npm i -D electron-rebuild , если она еще не установлена.
  • Удалите packages-lock.json из вашего проекта, если он существует
  • Запуск ./node_modules/.bin/electron-rebuild

Samples

  1. Пример электронного веб-пакета для сохраняемости
  2. Пример расширений msal-node