Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Вы можете создавать конфиденциальные клиентские приложения с помощью УЗЛА MSAL (веб-приложения, приложения управляющей программы и т. д.). Учетные данные клиента являются обязательными для конфиденциальных клиентов.
Необходимые условия
- Хорошее понимание инициализации конфиденциальных клиентских приложений.
Вы можете создавать конфиденциальные клиентские приложения с помощью УЗЛА MSAL (веб-приложения, приложения управляющей программы и т. д.). Учетные данные клиента являются обязательными для конфиденциальных клиентов. Учетные данные клиента могут быть следующими:
-
managed identity: это сценарий без сертификатов, где доверие устанавливается через инфраструктуру Azure. Не требуется управление секретами и сертификатами. MSAL пока не реализует эту функцию, но вместо этого можно использовать пакет SDK для удостоверений Azure. См. документацию по управляемым удостоверениям для ресурсов Azure -
clientSecret: секретная строка, сгенерированная во время регистрации приложения или обновленная после регистрации для существующего приложения. Не рекомендуется использовать в продакшене. -
clientCertificate: набор сертификатов во время регистрации приложения. Сертификат должен иметь закрытый ключ, так как он используется для подписывания утверждения , которое создает MSAL.thumbprintSha256представляет собой отпечаток сертификата X.509 SHA-256, аprivateKey— закрытый ключ в кодировке PEM. -
clientAssertion: вместо того, чтобы разрешить MSAL создать утверждение, разработчик приложения берет на себя контроль. Полезно для добавления дополнительных утверждений в утверждение или использования KeyVault для подписывания вместо локального сертификата. Сертификат, используемый для подписывания утверждения, по-прежнему необходимо задать во время регистрации приложения.
Примечание: приложения 1p также могут быть обязаны отправлять x5c. Это цепочка сертификатов X.509 , используемая в сценариях проверки подлинности субъекта или издателя.
Безопасное использование секретов и сертификатов
Секреты никогда не должны быть жестко закодированы. Пакет dotenv npm можно использовать для хранения секретов или сертификатов в env-файле (расположен в корневом каталоге проекта), который должен быть включен в gitignore, чтобы предотвратить случайные отправки секретов.
Сертификаты также можно считывать из файлов с помощью модуля fs NodeJS. Однако они никогда не должны храниться в каталоге проекта. Рабочие приложения должны получать сертификаты из Azure KeyVault или других защищенных хранилищ ключей.
Дополнительные сведения см. в сертификатах и секретах .
См. пример MSAL: auth-code-with-certs
Регистрация сертификатов
Если у вас нет сертификата, можно создать самозаверяющий сертификат с помощью PowerShell или с помощью Azure KeyVault.
Необходимо отправить сертификат в Microsoft Entra ID.
- Перейдите на портал Azure и выберите регистрацию приложения Microsoft Entra.
- Выберите слева раздел Сертификаты и секреты.
- Щелкните " Отправить сертификат" и выберите файл сертификата для отправки (например , example.crt).
- Нажмите кнопку Добавить. После отправки сертификата отображаются отпечаток (SHA-256),дата начала и значения срока действия .
Дополнительные сведения см. в статье "Регистрация сертификата с помощью платформа удостоверений Майкрософт
Инициализация MSAL Node с использованием сертификатов
const msal = require('@azure/msal-node');
require('dotenv').config(); // process.env now has the values defined in a .env file
const config = {
auth: {
clientId: "YOUR_CLIENT_ID",
authority: "https://login.microsoftonline.com/YOUR_TENANT_ID",
clientCertificate: {
thumbprintSha256: process.env.thumbprint,
privateKey: process.env.privateKey,
}
}
};
// Create msal application object
const cca = new msal.ConfidentialClientApplication(config);
Предполагается, что и thumbprintSha256, и privateKey являются строками.
privateKey также должен быть в следующем формате (PKCS#8):
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDkpKPrsfpIijS3
z2HCpDsa7dxOsKIrm7F1AtGBjyB0yVDjlh/FA7jT5sd2ypBh3FVsZGJudQsLRKfE
// ...
-----END ENCRYPTED PRIVATE KEY-----
Note
Кроме того, закрытый ключ может начинаться с -----BEGIN PRIVATE KEY----- (незашифрованный PKCS#8) или -----BEGIN RSA PRIVATE KEY----- (PKCS#1). Эти форматы также допустимы. Для преобразования любого совместимого ключа в тип ключа PKCS#8 можно использовать следующее:
openssl pkcs8 -topk8 -inform PEM -outform PEM -in example.key -out example.key
Если вы зашифровали закрытый ключ (или если ваш закрытый ключ уже зашифрован) с использованием парольной фразы, перед передачей в MSAL Node вам потребуется его расшифровать.
Важно: никогда не жестко кодировать пароли в исходном коде. Закрытый ключ сертификата и необязательный пароль дешифровки должны быть получены из безопасного расположения (например, Azure KeyVault) и развернуты безопасно с помощью веб-API.
Это можно сделать с помощью модуля crypto Node.js.
createPrivateKey() Используйте метод для синтаксического анализа и экспорта ключа:
const fs = require('fs');
const crypto = require('crypto');
const privateKeySource = fs.readFileSync('<path_to_key>/example.key')
const privateKeyObject = crypto.createPrivateKey({
key: privateKeySource,
passphrase: process.env.YOUR_PASSPHRASE,
format: 'pem'
});
const privateKey = privateKeyObject.export({
format: 'pem',
type: 'pkcs8'
});
(Необязательно) Преобразование pfx в pem
OpenSSL можно использовать для преобразования файлов сертификатов в формате pfx в pem:
openssl pkcs12 -in certificate.pfx -out certificate.pem
Если преобразование должно произойти программным способом, возможно, вам придется полагаться на сторонний пакет, так как Node.js не предлагает собственный метод для этого. Например, используя популярную реализацию TLS, такую как node-forge, можно сделать следующее:
const forge = require('node-forge');
/**
* @param {string} pfx: certificate + private key combination in pfx format
* @param {string} passphrase: passphrase used to encrypt pfx file
* @returns {Object}
*/
function convertPFX(pfx, passphrase = null) {
const asn = forge.asn1.fromDer(forge.util.decode64(pfx));
const p12 = forge.pkcs12.pkcs12FromAsn1(asn, true, passphrase);
// Retrieve key data
const keyData = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag })[forge.pki.oids.pkcs8ShroudedKeyBag]
.concat(p12.getBags({ bagType: forge.pki.oids.keyBag })[forge.pki.oids.keyBag]);
// Retrieve certificate data
const certBags = p12.getBags({ bagType: forge.pki.oids.certBag })[forge.pki.oids.certBag];
const certificate = forge.pki.certificateToPem(certBags[0].cert)
// Convert a Forge private key to an ASN.1 RSAPrivateKey
const rsaPrivateKey = forge.pki.privateKeyToAsn1(keyData[0].key);
// Wrap an RSAPrivateKey ASN.1 object in a PKCS#8 ASN.1 PrivateKeyInfo
const privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey);
// Convert a PKCS#8 ASN.1 PrivateKeyInfo to PEM
const privateKey = forge.pki.privateKeyInfoToPem(privateKeyInfo);
console.log("Converted certificate: \n", certificate);
console.log("Converted key: \n", privateKey);
return {
certificate: certificate,
key: privateKey
};
}
(Необязательно) Создание HTTPS-сервера
Протокол OAuth 2.0 рекомендует по возможности использовать подключение HTTPS. Большинство облачных служб, таких как Служба приложений Azure, по умолчанию предоставляют подключение HTTPS через прокси-сервер. Если для тестирования вы хотите настроить собственный HTTPS-сервер, ознакомьтесь с Node.js документацией по созданию HTTPS-сервера.
Кроме того, необходимо добавить свои самоподписанные сертификаты в диспетчер учетных данных / связку ключей вашей ОС, чтобы обойти политику безопасности браузера. После этого в браузере может отображаться предупреждение (например, Chrome).
Для Windows пользователей следуйте инструкциям в руководстве. Просмотр сертификатов с помощью оснастки MMC.
Для пользователей Linux и MacOS обратитесь к документации по операционной системе по установке сертификатов.
Предупреждение
Для выполнения приведенных выше команд может потребоваться права администратора .
Распространенные проблемы
В некоторых случаях при попытке пройти проверку подлинности с помощью сертификатов вы можете получить от Microsoft Entra ID ошибку, например AADSTS700027: Client assertion contains an invalid signature, указывающую на то, что сертификаты и/или закрытые ключи, которые вы используете для инициализации MSAL Node, имеют неверный формат. Распространенная причина заключается в том, что строка сертификата или закрытого ключа, которую вы предоставляете для узла MSAL, содержит непредвиденные символы, такие как возвращаемые каретки (\r) или новые строки (\n):
-----BEGIN CERTIFICATE-----\nMIIDDzCCAfegAwIBAgIJAMkyzQVK88NHMA0GCSqGSIb3DQEBBQUAMIGCMQswCQYDVQQGEwJTRTESMBAGA1UECBMJU3RvY2tob2xtMQ4wDAYDVQQHEwVLaXN0YTEQMA4G0fbkqbKulrchGbNgkankZtEVg4PGjobZq7B+njvcVa7SsWF/WLq5AUbw==\r\n-----END CERTIFICATE-----
Кроме того, файл сертификата или ключа может содержать атрибуты контейнера:
Bag Attributes
localKeyID: 28 B5 8E 16 11 88 E9 00 58 D5 76 30 12 B9 59 B8 E4 CE 7C AA
subject=/C=UK/ST=Suffolk/L=Ipswich/O=Example plc/CN=alice
issuer=/C=UK/ST=Suffolk/L=Ipswich/O=Example plc/CN=Certificate Authority/emailAddress=ca@example.com\n
-----BEGIN CERTIFICATE-----
MIIDDzCCAfegAwIBAgIJAMkyzQVK88NHMA0GCSqGSIb3DQEBBQUAMIGCMQswCQYD
VQQGEwJTRTESMBAGA1UECBMJU3RvY2tob2xtMQ4wDAYDVQQHEwVLaXN0YTEQMA4G
0fbkqbKulrchGbNgkankZtEVg4PGjo+Y8MdMjtfSZB29hwYvfMX09jzJ68ZqmpYQ
njvcVtLbEZN5OGCkaslb/f2OxLbsUNgIbws538WnaaufDvKmQe2kUdWmpl9Wn9Bf
bZq7B+njvcVa7SsWF/WLq5AUbw==
-----END CERTIFICATE-----
В таких случаях вы отвечаете за очистку строки перед передачей её в конфигурацию MSAL Node. Например:
const msal = require('@azure/msal-node');
const fs = require('fs');
const privateKeySource = fs.readFileSync('<path_to_key>/certs/example.key');
const privateKey = Buffer.from(privateKeySource, 'base64').toString().replace(/\r/g, "").replace(/\n/g, "");
const config = {
auth: {
clientId: "YOUR_CLIENT_ID",
authority: "https://login.microsoftonline.com/YOUR_TENANT_ID",
clientCertificate: {
thumbprintSha256: process.env.thumbprint,
privateKey: privateKey,
}
}
};
// Create msal application object
const cca = new msal.ConfidentialClientApplication(config);