Använda certifikatautentiseringsuppgifter med MSAL Node

Du kan skapa konfidentiella klientprogram med MSAL Node (webbappar, daemon-appar osv.). En klientautentiseringsuppgift är obligatorisk för konfidentiella klienter.

Förutsättningar

Du kan skapa konfidentiella klientprogram med MSAL Node (webbappar, daemon-appar osv.). En klientautentiseringsuppgift är obligatorisk för konfidentiella klienter. Klientautentiseringsuppgifter kan vara:

  • managed identity: Det här är ett certifikatlöst scenario där förtroende upprättas via Azure infrastruktur. Ingen hemlighet/certifikathantering krävs. MSAL implementerar ännu inte den här funktionen, men du kan använda Azure Identity SDK i stället. Se dokumentationen om hanterade identiteter för Azure-resurser
  • clientSecret: en hemlig sträng som genererades under appregistreringen eller uppdaterade efter registreringen för ett befintligt program. Detta rekommenderas inte för produktion.
  • clientCertificate: ett certifikat som angetts under appregistreringen. Certifikatet måste ha den privata nyckeln eftersom det används för att signera ett intyg som MSAL genererar. thumbprintSha256 är ett X.509 SHA-256 tumavtryck för certifikatet och privateKey är den PEM-kodade privata nyckeln.
  • clientAssertion: I stället för att låta MSAL skapa en försäkran tar apputvecklaren kontroll. Användbart för att lägga till extra anspråk i försäkran eller för att använda KeyVault för signering, i stället för ett lokalt certifikat. Certifikatet som används för att signera försäkran måste fortfarande anges under appregistreringen.

Obs! 1p-appar kan också behöva skicka x5c. Det här är X.509-certifikatkedjan som används i autentiseringsscenarier med ämnesnamn/utfärdare.

Använda hemligheter och certifikat på ett säkert sätt

Hemligheter ska aldrig hårdkodas. Dotenv npm-paketet kan användas för att lagra hemligheter eller certifikat i en .env-fil (finns i projektets rotkatalog) som ska ingå i .gitignore för att förhindra oavsiktliga uppladdningar av hemligheterna.

Certifikat kan också läsas in från filer via NodeJS fs-modul. De bör dock aldrig lagras i projektets katalog. Produktionsappar bör hämta certifikat från Azure KeyVault eller andra säkra nyckelvalv.

Mer information finns i certifikat och hemligheter .

Se MSAL-exemplet: auth-code-with-certs

Registrera certifikat

Om du inte har något certifikat kan du skapa ett självsignerat certifikat med PowerShell eller använda Azure KeyVault.

Du måste ladda upp certifikatet till Microsoft Entra ID.

  1. Gå till Azure portalen och välj din Microsoft Entra appregistrering.
  2. Välj bladet Certifikat och hemligheter till vänster.
  3. Klicka på Ladda upp certifikat och välj den certifikatfil som ska laddas upp (t.ex. example.crt).
  4. Klicka på Lägg till. När certifikatet har laddats upp visas tumavtrycket (SHA-256),startdatum och förfallovärden .

Mer information finns i: Registrera ditt certifikat med Microsofts identitetsplattform

Initiera MSAL-nod med certifikat

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

Både thumbprintSha256 och privateKey förväntas vara strängar. privateKey förväntas vara i följande form (PKCS#8):

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDkpKPrsfpIijS3
z2HCpDsa7dxOsKIrm7F1AtGBjyB0yVDjlh/FA7jT5sd2ypBh3FVsZGJudQsLRKfE
// ...
-----END ENCRYPTED PRIVATE KEY-----

Note

Alternativt kan din privata nyckel börja med -----BEGIN PRIVATE KEY----- (okrypterad PKCS#8) eller -----BEGIN RSA PRIVATE KEY----- (PKCS#1). Dessa format är också tillåtna. Följande kan användas för att konvertera valfri kompatibel nyckel till nyckeltypen PKCS#8:

openssl pkcs8 -topk8 -inform PEM -outform PEM -in example.key -out example.key

Om du har krypterat din privata nyckel (eller om din privata nyckel redan är krypterad) med en lösenordsfras måste du dekryptera den innan du skickar den till MSAL Node.

Viktigt: Hårdkoda aldrig lösenord i källkoden. Både certifikatets privata nyckel och det valfria deskrypteringslösenordet ska hämtas från en säker plats (t.ex. Azure KeyVault) och distribueras säkert med webb-API:et.

Detta kan göras med hjälp av Nodes kryptomodul. createPrivateKey() Använd metoden för att parsa och exportera din nyckel:

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

(Valfritt) Konvertera pfx till pem

OpenSSL kan användas för att konvertera pfx-kodade certifikatfiler till pem:

    openssl pkcs12 -in certificate.pfx -out certificate.pem

Om konverteringen måste ske programmatiskt kan du behöva förlita dig på ett tredjepartspaket, eftersom Node.js inte erbjuder någon intern metod för detta. Om du till exempel använder en populär TLS-implementering som node-forge kan du göra:

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

(Valfritt) Skapa en HTTPS-server

OAuth 2.0-protokollet rekommenderar att du använder en HTTPS-anslutning när det är möjligt. De flesta molntjänster som Azure App Service tillhandahåller HTTPS-anslutning som standard via proxy. Om du vill konfigurera en egen HTTPS-server i testsyfte kan du läsa dokumentationen om Node.js för vägledning om hur du skapar en HTTPS-server.

Du måste också lägga till dina självsignerade certifikat inyckelkedjan för / operativsystemet för att kringgå webbläsarens säkerhetsprincip. Du kan fortfarande se en varning i webbläsaren efteråt (t.ex. Chrome).

Varning

Du kan behöva administratörsbehörighet för att köra kommandona ovan.

Vanliga problem

I vissa fall kan du få ett fel från Microsoft Entra ID när du försöker autentisera med certifikat, till exempel felet AADSTS700027: Client assertion contains an invalid signature, vilket anger att de certifikat och/eller privata nycklar som du använder för att initiera MSAL Node är felaktigt formaterade. En vanlig orsak till detta är att certifikatet/den privata nyckelsträngen som du anger till MSAL Node innehåller oväntade tecken, till exempel returvagnar (\r) eller nya raderna (\n):

-----BEGIN CERTIFICATE-----\nMIIDDzCCAfegAwIBAgIJAMkyzQVK88NHMA0GCSqGSIb3DQEBBQUAMIGCMQswCQYDVQQGEwJTRTESMBAGA1UECBMJU3RvY2tob2xtMQ4wDAYDVQQHEwVLaXN0YTEQMA4G0fbkqbKulrchGbNgkankZtEVg4PGjobZq7B+njvcVa7SsWF/WLq5AUbw==\r\n-----END CERTIFICATE-----

Alternativt kan ditt certifikat / din nyckelfil innehålla bag attributes:

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-----

I sådana fall ansvarar du för att rensa strängen innan du skickar dem till MSAL Node-konfigurationen. Till exempel:

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

Se även