Миграция приложения Node.js из ADAL в MSAL
Сейчас рекомендуется использовать библиотеку проверки подлинности Майкрософт для Node (MSAL Node). Это рекомендуемый пакет SDK для включения проверки подлинности и авторизации для приложений, зарегистрированных на платформе Microsoft Identity. В этой статье рассматриваются важные шаги, которые необходимо выполнить, чтобы перенести приложения из библиотеки проверки подлинности Active Directory для Node (ADAL Node) в приложение MSAL Node.
Необходимые компоненты
- Node версии 10, 12, 14, 16 или 18. См. Примечание о поддержке версий
Обновление параметров регистрации приложения
При работе с ADAL Node, скорее всего, вы использовали конечную точку Azure AD версии 1.0. Приложения, перенесенные из ADAL в MSAL, должны переключиться на конечную точку Azure AD версии 2.0.
Установка и импорт MSAL
- установите пакет УЗЛА MSAL через npm:
npm install @azure/msal-node
- После этого импортируйте MSAL Node в код:
const msal = require('@azure/msal-node');
- Наконец, удалите пакет ADAL Node и все ссылки на него в коде:
npm uninstall adal-node
Инициализация MSAL
В ADAL Node вы инициализируете AuthenticationContext
объект, который затем предоставляет методы, которые можно использовать в разных потоках проверки подлинности (например, acquireTokenWithAuthorizationCode
для веб-приложений). При инициализации единственным обязательным параметром является URI центра авторизации:
var adal = require('adal-node');
var authorityURI = "https://login.microsoftonline.com/common";
var authenticationContex = new adal.AuthenticationContext(authorityURI);
В MSAL Node вместо этого есть два варианта: если вы создаете мобильное приложение или классическое приложение, создается экземпляр PublicClientApplication
объекта. Конструктор ожидает объект конфигурации, который содержит по крайней мере параметр clientId
. MSAL по умолчанию использует универсальный код ресурса (URI https://login.microsoftonline.com/common
) центра, если он не указан.
const msal = require('@azure/msal-node');
const pca = new msal.PublicClientApplication({
auth: {
clientId: "YOUR_CLIENT_ID"
}
});
Примечание.
Если вы используете https://login.microsoftonline.com/common
центр в версии 2.0, пользователи смогут войти с помощью любой организации Microsoft Entra или личной учетной записи Майкрософт (MSA). В MSAL Node, если вы хотите ограничить вход любой учетной записью Microsoft Entra (то же поведение, что и с adAL Node), используйте https://login.microsoftonline.com/organizations
вместо этого.
С другой стороны, если вы создаете веб-приложение или управляющее приложение, создается экземпляр ConfidentialClientApplication
объекта. С такими приложениями также необходимо указать учетные данные клиента, например секрет или сертификат клиента:
const msal = require('@azure/msal-node');
const cca = new msal.ConfidentialClientApplication({
auth: {
clientId: "YOUR_CLIENT_ID",
clientSecret: "YOUR_CLIENT_SECRET"
}
});
PublicClientApplication
и ConfidentialClientApplication
, в отличие от ADAL AuthenticationContext
, привязаны к идентификатору клиента. Это означает, что при наличии различных идентификаторов клиентов, которые вы хотите использовать в приложении, необходимо создать еще по одному экземпляру MSAL для каждого из них. Дополнительные сведения см. в разделе Инициализация MSAL Node
Настройка MSAL
При создании приложений на платформе Microsoft Identity приложение будет содержать много параметров, связанных с проверкой подлинности. В adAL Node AuthenticationContext
объект имеет ограниченное количество параметров конфигурации, с помощью которых можно создать экземпляр, а остальные параметры зависают свободно в коде (например, 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-адрес, определяющий центр авторизации токеновvalidateAuthority
: возможность, которая не позволяет коду запрашивать токены от потенциально вредоносного центра авторизацииcache
: задает кэш токенов, используемый этим экземпляром AuthenticationContext. Если этот параметр не задан, то используется значение по умолчанию в кэше памяти.
MSAL Node, с другой стороны, использует объект конфигурации типа Configuration. Он содержит следующие свойства:
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);
В качестве заметной разницы MSAL не имеет флага, чтобы отключить проверку центра и центры всегда проверяются по умолчанию. MSAL сравнивает запрошенный центр авторизации со списком центров авторизации, известных корпорации Майкрософт, или со списком центров авторизации, указанных в конфигурации. Дополнительная информация: Параметры конфигурации
Переход на API MSAL
Для большинства открытых методов в ADAL Node имеются эквиваленты в MSAL Node:
ADAL | MSAL | Примечания. |
---|---|---|
acquireToken |
acquireTokenSilent |
Переименован и теперь ожидается объект учетной записи |
acquireTokenWithAuthorizationCode |
acquireTokenByCode |
|
acquireTokenWithClientCredentials |
acquireTokenByClientCredential |
|
acquireTokenWithRefreshToken |
acquireTokenByRefreshToken |
Применяется для миграции допустимых маркеров обновления |
acquireTokenWithDeviceCode |
acquireTokenByDeviceCode |
Теперь абстрагирует получение кода пользователя (см. ниже) |
acquireTokenWithUsernamePassword |
acquireTokenByUsernamePassword |
Однако некоторые методы в ADAL Node являются устаревшими, тогда как в MSAL Node доступны новые методы:
ADAL | MSAL | Примечания. |
---|---|---|
acquireUserCode |
Н/П | Объединен с acquireTokeByDeviceCode (см. выше) |
Н/П | acquireTokenOnBehalfOf |
Новый метод, который абстрагирует поток OBO |
acquireTokenWithClientCertificate |
Н/П | Больше не требуется, так как теперь сертификаты назначаются в процессе инициализации (см. Параметры конфигурации) |
Н/П | getAuthCodeUrl |
Новый метод, который абстрагирует создание URL-адресов конечных точек авторизации |
Использование областей вместо ресурсов
Важное различие между конечными точками версии 1.0 и 2.0 заключается в том, как осуществляется доступ к ресурсам. В ADAL Node сначала необходимо зарегистрировать разрешение на портале регистрации приложений, а затем запросить токен доступа для ресурса (например, Microsoft Graph), как показано ниже:
authenticationContext.acquireTokenWithAuthorizationCode(
req.query.code,
redirectUri,
resource, // e.g. 'https://graph.microsoft.com'
clientId,
clientSecret,
function (err, response) {
// do something with the authentication response
}
);
MSAL Node поддерживает только конечную точку версии 2.0 . Конечная точка версии 2.0 использует модель доступа к ресурсам на основе областей. Таким образом, при запросе токена доступа для ресурса также необходимо указать область для этого ресурса:
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);
});
Одним из преимуществ модели на основе областей является возможность использовать динамические области. При создании приложений с использованием версии 1.0 нужно было регистрировать полный набор разрешений (статические области), которые пользователь должен подтверждать во время входа в приложение. В версии 2.0 можно использовать параметр области, который может запросить разрешения в тот момент, когда они нужны (т. е. динамические области). Это позволяет пользователю дополнять список подтвержденных разрешений для областей. Таким образом, в начале работы вы можете позволить пользователю просто войти в приложение без запроса прав доступа, если они пока не нужны. Позже, когда потребуется возможность чтения календаря пользователя, вы укажете область календаря в методе получения маркера и получите согласие пользователя. Дополнительные сведения см. в разделе Ресурсы и области
Использование обещаний вместо обратных вызовов
В ADAL Node обратные вызовы используются для любой операции после успешной проверки подлинности и получения ответа:
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
}
});
В MSAL Node вместо них используются обещания:
const cca = new msal.ConfidentialClientApplication(msalConfig);
cca.acquireTokenByClientCredential(tokenRequest).then((response) => {
// do something with the authentication response
}).catch((error) => {
console.log(error);
});
Также можно использовать синтаксис async/await, входящий в состав ES8:
try {
const authResponse = await cca.acquireTokenByCode(tokenRequest);
} catch (error) {
console.log(error);
}
Включение ведения журналов
В ADAL Node необходимо отдельно настраивать ведение журнала в любом месте кода:
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.
});
В MSAL Node ведение журнала относится к параметрам конфигурации и устанавливается при инициализации экземпляра MSAL Node:
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);
Включение кэширования маркеров
В ADAL Node имеется возможность импортировать кэш токенов в памяти. Кэш токенов используется в качестве параметра при инициализации объекта AuthenticationContext
:
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);
MSAL Node по умолчанию использует кэш токенов в памяти. Не нужно явно импортировать его; Кэш маркеров в памяти предоставляется как часть ConfidentialClientApplication
и PublicClientApplication
классы.
const msalTokenCache = publicClientApplication.getTokenCache();
Важно отметить, что предыдущий кэш маркеров с помощью узла ADAL не будет передаваться в MSAL Node, так как схемы кэша несовместимы. Однако вы можете использовать в MSAL Node действительные маркеры обновления, полученные ранее с помощью ADAL Node. Дополнительные сведения см. в разделе о маркерах обновления.
Вы также можете записать кэш на диск, используя собственный подключаемый модуль кэша. Подключаемый модуль кэша должен реализовать интерфейс ICachePlugin
. Как и ведение журнала, кэширование относится к параметрам конфигурации и устанавливается при инициализации экземпляра MSAL Node:
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);
Пример подключаемого модуля кэша можно продемонстрировать следующим образом:
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
};
Если вы разрабатываете общедоступные клиентские приложения , такие как классические приложения, расширения проверки подлинности Майкрософт для Node предлагают безопасные механизмы для клиентских приложений для выполнения сериализации и сохраняемости межплатформенного кэша маркеров. Поддерживаются платформы Windows, Mac и Linux.
Примечание.
Расширения для проверки подлинности Майкрософт для Node не рекомендуется использовать для веб-приложений, так как это может привести к проблемам масштабирования и производительности. Вместо этого для сохранения кэша в сеансе рекомендуется использовать веб-приложения.
Удаление логики, касающейся токенов обновления
В ADAL Node появились токены обновления (RT), что позволяет создавать решения с использованием таких токенов путем их кэширования и применения метода acquireTokenWithRefreshToken
. Типичные сценарии, когда RT особенно важны:
- Длительные службы, которые выполняют действия (в том числе обновление панелей мониторинга) от имени пользователя, когда пользователь уже закрыл подключение.
- Предоставление клиенту возможности применить RT для веб-службы в сценарии WebFarm (кэширование выполняется на стороне клиента с использованием зашифрованного файла cookie, а не на стороне сервера).
Узел MSAL, а также другие msALs, не предоставляет маркеры обновления по соображениям безопасности. Вместо этого MSAL обрабатывает токены обновления. Поэтому вам больше не нужно создавать эту логику. Однако вы можете использовать полученные ранее (и сохраняющие действительность) маркеры обновления из кэша ADAL Node, чтобы получить новый набор маркеров для MSAL Node. Для этого MSAL Node предлагает acquireTokenByRefreshToken
— эквивалент метода acquireTokenWithRefreshToken
в ADAL Node:
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);
});
Дополнительные сведения см. в примере миграции с ADAL Node на MSAL Node.
Примечание.
Если вы используете сохраняющие допустимость маркеры обновления для получения нового набора маркеров с помощью метода узла MSAL acquireTokenByRefreshToken
, как показано выше, рекомендуется уничтожить старый кэш маркеров ADAL Node.
Обработка ошибок и исключений
При использовании MSAL Node наиболее распространенным типом ошибки может стать interaction_required
. Эта ошибка часто устраняется путем инициирования запроса на получение интерактивных маркеров. Например, при использовании acquireTokenSilent
при отсутствии кэшированных маркеров обновления узел MSAL не сможет автоматически получить маркер доступа. Аналогичным образом, веб-API, к которому вы пытаетесь получить доступ, может иметь политику условного доступа, требуя от пользователя выполнения многофакторной проверки подлинности (MFA). В этом случае обработка ошибки interaction_required
путем запуска acquireTokenByCode
приведет к появлению у пользователя запроса на MFA, позволяя ее пройти.
Еще одна распространенная ошибка, consent_required
которая возникает, когда разрешения, необходимые для получения маркера доступа для защищенного ресурса, не получают согласия пользователя. Как и в случае с interaction_required
, для устранения ошибки consent_required
зачастую необходимо инициализировать интерактивный запрос на получение маркера с использованием метода acquireTokenByCode
.
Выполнить приложение
После внесения изменений запустите приложение и протестируйте сценарий проверки подлинности:
npm start
Пример: получение маркеров с помощью ADAL Node и MSAL Node
В приведенном ниже фрагменте кода демонстрируется конфиденциальное клиентское веб-приложение на платформе Express.js. Он выполняет вход, когда пользователь обращается к маршруту проверки подлинности /auth
, получает токен доступа для Microsoft Graph через маршрут /redirect
, а затем отображает содержимое указанного токена.
Использование узла ADAL | Использование узла MSAL |
|
|