Certificaatreferenties gebruiken met MSAL Node

U kunt vertrouwelijke clienttoepassingen bouwen met MSAL Node (web-apps, daemon-apps, enzovoort). Een clientreferentie is verplicht voor vertrouwelijke clients.

Prerequisites

U kunt vertrouwelijke clienttoepassingen bouwen met MSAL Node (web-apps, daemon-apps, enzovoort). Een clientreferentie is verplicht voor vertrouwelijke clients. Clientaanmeldingsgegevens kunnen zijn:

  • managed identity: dit is een certificaatloos scenario, waarbij een vertrouwensrelatie tot stand wordt gebracht via de Azure-infrastructuur. Er is geen geheim/certificaatbeheer vereist. MSAL implementeert deze functie nog niet, maar u kunt in plaats daarvan Azure Identity SDK gebruiken. Raadpleeg de documentatie voor beheerde identiteiten voor Azure resources
  • clientSecret: een geheime tekenreeks die is gegenereerd tijdens de app-registratie of een bijgewerkte postregistratie voor een bestaande toepassing. Dit wordt niet aanbevolen voor productie.
  • clientCertificate: een certificaat dat is ingesteld tijdens de app-registratie. Het certificaat moet de persoonlijke sleutel hebben, omdat deze wordt gebruikt voor het ondertekenen van een verklaring die DOOR MSAL wordt gegenereerd. Het thumbprintSha256 is een X.509 SHA-256-vingerafdruk van het certificaat en de privateKey met PEM gecodeerde persoonlijke sleutel.
  • clientAssertion: in plaats van MSAL een assertie te laten maken, neemt de app-ontwikkelaar de besturing over. Handig voor het toevoegen van extra claims aan de assertie of voor het gebruik van KeyVault voor ondertekening, in plaats van een lokaal certificaat. Het certificaat dat wordt gebruikt om de assertie te ondertekenen, moet nog steeds worden ingesteld tijdens de app-registratie.

Opmerking: 1p-apps moeten mogelijk ook x5c verzenden. Dit is de X.509-certificaatketen die wordt gebruikt in verificatiescenario's voor onderwerpnaam/verlener.

Geheimen en certificaten veilig gebruiken

Geheimen mogen nooit hardcoded worden. Het dotenv npm-pakket kan worden gebruikt voor het opslaan van geheimen of certificaten in een .env-bestand (in de hoofdmap van het project) dat moet worden opgenomen in .gitignore om onbedoelde uploads van de geheimen te voorkomen.

Certificaten kunnen ook worden gelezen vanuit bestanden via de fs-module van NodeJS. Ze mogen echter nooit worden opgeslagen in de map van het project. Productie-apps moeten certificaten ophalen uit Azure KeyVault of andere beveiligde sleutelkluizen.

Raadpleeg certificaten en geheimen voor meer informatie.

Zie het MSAL-voorbeeld: auth-code-with-certs

Certificaten registreren

Als u geen certificaat hebt, kunt u een zelfondertekend certificaat maken met behulp van PowerShell of met behulp van Azure KeyVault.

U moet uw certificaat uploaden naar Microsoft Entra ID.

  1. Ga naar Azure portal en selecteer uw Microsoft Entra app-registratie.
  2. Selecteer de blade Certificaten en geheimen aan de linkerkant.
  3. Klik op Certificaat uploaden en selecteer het certificaatbestand dat u wilt uploaden (bijvoorbeeld example.crt).
  4. Klik op Toevoegen. Zodra het certificaat is geüpload, worden de vingerafdruk (SHA-256), de begindatum en de vervaldatum weergegeven.

Zie voor meer informatie: Uw certificaat registreren bij Microsoft identity platform

MSAL-knooppunt initialiseren met certificaten

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

Zowel thumbprintSha256 als privateKey worden geacht tekenreeksen te zijn. privateKey wordt daarnaast in de volgende vorm verwacht (PKCS#8):

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

Note

Uw persoonlijke sleutel kan ook beginnen met -----BEGIN PRIVATE KEY----- (niet-versleutelde PKCS#8) of -----BEGIN RSA PRIVATE KEY----- (PKCS#1). Deze indelingen zijn ook toegestaan. Het volgende kan worden gebruikt om elke compatibele sleutel te converteren naar het sleuteltype PKCS#8:

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

Als u uw persoonlijke sleutel hebt versleuteld (of als uw persoonlijke sleutel al is versleuteld) met een wachtwoordzin, moet u deze ontsleutelen voordat u deze doorgeeft aan MSAL Node.

Belangrijk: Codeer nooit wachtwoorden in broncode. Zowel de persoonlijke sleutel van het certificaat als het optionele ontsleutelingswachtwoord moeten worden opgehaald van een veilige locatie (bijvoorbeeld Azure KeyVault) en veilig worden geïmplementeerd met uw web-API.

Dit kan worden gedaan met behulp van de cryptomodule van Node. Gebruik de createPrivateKey() methode om uw sleutel te parseren en exporteren:

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

(Optioneel) Pfx converteren naar pem

OpenSSL kan worden gebruikt voor het converteren van pfx-gecodeerde certificaatbestanden naar pem:

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

Als de conversie programmatisch moet plaatsvinden, moet u mogelijk vertrouwen op een pakket van derden, omdat Node.js hiervoor geen systeemeigen methode biedt. Als u bijvoorbeeld een populaire TLS-implementatie gebruikt, zoals node-forge, kunt u het volgende doen:

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

(Optioneel) Een HTTPS-server maken

Het OAuth 2.0-protocol raadt aan om waar mogelijk een HTTPS-verbinding te gebruiken. De meeste cloudservices zoals Azure App Service bieden standaard HTTPS-verbinding via proxy. Als u voor testdoeleinden uw eigen HTTPS-server wilt instellen, raadpleegt u de Node.js documentatie voor hulp bij het maken van een HTTPS-server.

U moet ook uw zelfondertekende certificaten toevoegen aan de sleutelketen referentiebeheer / van uw besturingssysteem om het beveiligingsbeleid van de browser te omzeilen. Mogelijk ziet u later nog steeds een waarschuwing in uw browser (bijvoorbeeld Chrome).

  • Volg de handleiding voor Windows gebruikers hier: Certificaten weergeven met de MMC-module.

  • Voor Linux- en MacOS-gebruikers raadpleegt u de documentatie van uw besturingssysteem over het installeren van certificaten.

Warning

Mogelijk hebt u beheerdersbevoegdheden nodig voor het uitvoeren van de bovenstaande opdrachten.

Veelvoorkomende problemen

In sommige gevallen krijgt u mogelijk een foutmelding van Microsoft Entra ID bij het verifiëren met behulp van certificaten, zoals de AADSTS700027: Client assertion contains an invalid signature fout, waarmee wordt aangegeven dat de certificaten en/of persoonlijke sleutels die u gebruikt om MSAL Node te initialiseren, onjuist zijn. Een veelvoorkomende reden hiervoor is dat de certificaat- of privésleutelreeks die u aan MSAL Node doorgeeft, onverwachte tekens bevat, zoals carriage returns (\r) of regeleinden (\n):

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

Als alternatief kan uw certificaat-/sleutelbestand bag-attributen bevatten:

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

In dergelijke gevallen bent u verantwoordelijk voor het opschonen van de tekenreeks voordat u deze doorgeeft aan de configuratie van MSAL Node. Bijvoorbeeld:

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

Zie ook