你可以用 MSAL Node 建立機密客戶端應用程式(網頁應用程式、守護程序應用程式等)。 機密客戶必須擁有 客戶憑證 。
先決條件
- 充分了解 初始化機密用戶端應用程式。
你可以用 MSAL Node 建立機密客戶端應用程式(網頁應用程式、守護程序應用程式等)。 機密客戶必須擁有 客戶憑證 。 客戶憑證可以是:
-
managed identity這是一種無憑證情境,透過 Azure 基礎設施建立信任。 不需要秘密或憑證管理。 MSAL 目前還沒有實作這個功能,但你可以改用 Azure Identity SDK。 請參閱 Azure 資源的受控識別文件 -
clientSecret:應用程式註冊過程中產生的秘密字串,或是現有應用程式更新的註冊後字串。 這不建議用於製作。 -
clientCertificate:在應用程式註冊時設定的憑證。 憑證必須包含私鑰,因為它是用來簽署 MSAL 產生的 斷言 。thumbprintSha256是憑證的 X.509 SHA-256 指紋,而privateKey是 PEM 編碼的私鑰。 -
clientAssertion:應用程式開發者不再讓 MSAL 建立 斷言,而是自行掌控。 對於在斷言中增加額外聲明或使用 KeyVault 來簽署,而非本地憑證,非常有用。 用於簽署斷言的憑證仍需在應用程式註冊時設定。
注意:1p 應用程式可能也必須發送 x5c。 這是用於主體名稱/發行者認證情境下的 X.509 憑證鏈。
安全使用秘密與憑證
秘密絕不應該被硬編碼。 dotenv npm 套件可用來將秘密或憑證儲存在 .env 檔案(位於專案根目錄中),這些檔案應包含在 .gitignore 中,以防止秘密誤上傳。
憑證也可以透過 NodeJS 的 fs 模組從檔案讀取。 然而,這些資料絕不應儲存在專案目錄中。 生產應用程式應該從 Azure KeyVault 或其他安全金鑰庫取得憑證。
詳情請參閱 證書與秘密 。
請參閱 MSAL 範例: auth-code-with-certs
註冊憑證
如果你沒有憑證,可以用 PowerShell 或 Azure KeyVault 建立自簽憑證。
你需要把你的憑證上傳到 Microsoft Entra ID。
- 進入 Azure 入口網站,選擇你的 Microsoft Entra 應用程式註冊。
- 在左側選取 憑證與祕密 頁面。
- 點選 「上傳 憑證」,選擇要上傳的憑證檔案(例如 example.crt)。
- 按一下新增。 憑證上傳後,會顯示指紋(SHA-256)、起始日期及到期時間。
欲了解更多資訊,請參見:向 Microsoft 身分識別平台 註冊您的憑證
以憑證初始化 MSAL 節點
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 安全部署。
這可以透過 Node 的 加密模組來完成。 使用 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 沒有原生方法。 例如,使用像 node-forge 這樣的熱門 TLS 實作,你可以做到:
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 App 服務 預設會透過代理提供 HTTPS 連線。 如果你想測試自己架設 HTTPS 伺服器,請參考 Node.js 文件中的 HTTPS 伺服器建立指引。
你還需要將自簽憑證加入作業系統的 / 鑰匙串,以繞過瀏覽器的安全政策。 之後你仍可能在瀏覽器(例如 Chrome 上)看到警告。
對於 Windows 使用者,請參考此處的指南:如何:使用 MMC snap-in 查看憑證。
對於 Linux 和 MacOS 使用者,請參閱作業系統文件中如何安裝憑證。
Warning
執行上述指令可能需要管理員權限。
常見問題
在某些情況下,當你嘗試使用憑證驗證時,可能會收到 Microsoft Entra ID 錯誤,例如AADSTS700027: Client assertion contains an invalid signature這個錯誤,表示你用來初始化 MSAL Node 的憑證和/或私鑰是格式錯誤的。 常見原因是你提供給 MSAL Node 的憑證/私鑰字串包含意料之外的字元,例如 回傳行位 (\r)或 換行 (\n):
-----BEGIN CERTIFICATE-----\nMIIDDzCCAfegAwIBAgIJAMkyzQVK88NHMA0GCSqGSIb3DQEBBQUAMIGCMQswCQYDVQQGEwJTRTESMBAGA1UECBMJU3RvY2tob2xtMQ4wDAYDVQQHEwVLaXN0YTEQMA4G0fbkqbKulrchGbNgkankZtEVg4PGjobZq7B+njvcVa7SsWF/WLq5AUbw==\r\n-----END CERTIFICATE-----
或者,您的憑證/金鑰檔案中可能包含 bag 屬性:
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);