Utilisation des informations d’identification de certificat avec MSAL Node

Vous pouvez créer des applications clientes confidentielles avec MSAL Node (applications web, applications démon, etc.). Les informations d’identification d’un client sont obligatoires pour les clients confidentiels.

Prerequisites

Vous pouvez créer des applications clientes confidentielles avec MSAL Node (applications web, applications démon, etc.). Les informations d’identification d’un client sont obligatoires pour les clients confidentiels. Les informations d’identification du client peuvent être les suivantes :

  • managed identity: il s’agit d’un scénario sans certificat, où l’approbation est établie via l’infrastructure Azure. Aucune gestion des secrets/certificats n’est requise. MSAL n'implémente pas encore cette fonctionnalité, mais vous pouvez utiliser Azure SDK Identity à la place. Consultez la documentation sur les identités gérées pour les ressources Azure
  • clientSecret: chaîne secrète générée pendant l’inscription de l’application ou mise à jour après l’inscription d’une application existante. Cela n’est pas recommandé en production.
  • clientCertificate: un certificat défini pendant l’inscription de l’application. Le certificat doit avoir la clé privée, car il est utilisé pour signer une assertion générée par MSAL. Le thumbprintSha256 est une empreinte X.509 SHA-256 du certificat, et le privateKey est la clé privée encodée au format PEM.
  • clientAssertion: au lieu de laisser MSAL créer une assertion, le développeur de l’application prend le contrôle. Utile pour ajouter des revendications supplémentaires à l’assertion ou pour utiliser KeyVault pour la signature, au lieu d’un certificat local. Le certificat utilisé pour signer l’assertion doit toujours être défini pendant l’inscription de l’application.

Remarque : les applications 1p peuvent également être tenues d’envoyer x5c. Il s’agit de la chaîne de certificats X.509 utilisée dans les scénarios d’authentification du sujet/de l’émetteur.

Utilisation sécurisée des secrets et des certificats

Les secrets ne doivent jamais être codés en dur. Le package npm dotenv peut être utilisé pour stocker des secrets ou des certificats dans un fichier .env (situé dans le répertoire racine du projet) qui doit être inclus dans .gitignore pour empêcher les chargements accidentels des secrets.

Les certificats peuvent également être en lecture à partir de fichiers via le module fs de NodeJS. Toutefois, ils ne doivent jamais être stockés dans le répertoire du projet. Les applications de production doivent extraire des certificats de Azure KeyVault ou d’autres coffres de clés sécurisés.

Pour plus d’informations, consultez les certificats et les secrets .

Consultez l’exemple MSAL : authentification-code-with-certs

Enregistrement des certificats

Si vous n’avez pas de certificat, vous pouvez créer un certificat auto-signé à l’aide de PowerShell ou d’Azure KeyVault.

Vous devez charger votre certificat sur Microsoft Entra ID.

  1. Accédez au portail Azure et sélectionnez votre inscription d’application Microsoft Entra.
  2. Sélectionnez le panneau Certificats et secrets sur la gauche.
  3. Cliquez sur Charger le certificat et sélectionnez le fichier de certificat à charger (par exemple.crt).
  4. Cliquez sur Ajouter. Une fois le certificat chargé, l’empreinte numérique (SHA-256), la date de début et les valeurs d’expiration sont affichées.

Pour plus d’informations, consultez : Inscrire votre certificat auprès de Plateforme d'identités Microsoft

Initialisation du nœud MSAL avec des certificats

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 et privateKey doivent tous deux être des chaînes. privateKey devrait être au format suivant (PKCS#8) :

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

Note

Vous pouvez également commencer -----BEGIN PRIVATE KEY----- par votre clé privée ( PKCS#8 non chiffré) ou -----BEGIN RSA PRIVATE KEY----- (PKCS#1). Ces formats sont également autorisés. Vous pouvez utiliser ce qui suit pour convertir n’importe quelle clé compatible en type de clé PKCS#8 :

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

Si vous avez chiffré votre clé privée (ou si votre clé privée est déjà chiffrée) avec une expression de passe, vous devez le déchiffrer avant de le transmettre au nœud MSAL.

Important : Ne jamais coder en dur les mots de passe dans le code source. La clé privée du certificat et le mot de passe de déchiffrement facultatif doivent être récupérés à partir d’un emplacement sécurisé (par exemple, Azure KeyVault) et déployés en toute sécurité avec votre API web.

Cette opération peut être effectuée à l’aide du module de chiffrement de Node. Utilisez la createPrivateKey() méthode pour analyser et exporter votre clé :

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

(Facultatif) Conversion de pfx en pem

OpenSSL peut être utilisé pour convertir des fichiers de certificat encodés pfx en pem :

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

Si la conversion doit se produire par programmation, vous devrez peut-être vous appuyer sur un package tiers, car Node.js n’offre aucune méthode native pour cela. Par exemple, à l’aide d’une implémentation TLS populaire comme la forge de nœuds, vous pouvez effectuer les étapes suivantes :

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

(Facultatif) Création d’un serveur HTTPS

Le protocole OAuth 2.0 recommande d’utiliser une connexion HTTPS dans la mesure du possible. La plupart des services cloud comme Azure App Service fournissent une connexion HTTPS par défaut via un proxy. Si, à des fins de test, vous souhaitez configurer votre propre serveur HTTPS, consultez la documentation Node.js pour obtenir des conseils sur la création d’un serveur HTTPS.

Vous devez également ajouter vos certificats auto-signés à lachaîne de clés du gestionnaire / d’informations d’identificationde votre système d’exploitation pour contourner la stratégie de sécurité du navigateur. Vous pouvez toujours voir un avertissement dans votre navigateur par la suite (par exemple Chrome).

Warning

Vous pouvez avoir besoin de privilèges d’administrateur pour exécuter les commandes ci-dessus.

Problèmes courants

Dans certains cas, vous pouvez recevoir une erreur de Microsoft Entra ID lors de la tentative d’authentification à l’aide de certificats, comme l’erreurAADSTS700027: Client assertion contains an invalid signature, indiquant que les certificats et/ou les clés privées que vous utilisez pour initialiser le nœud MSAL sont mal formés. Une raison courante est que le certificat/chaîne de clé privée que vous fournissez à MSAL Node contient des caractères inattendus, tels que les chariots de retour (\r) ou les lignes de nouvelle ligne (\n) :

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

Sinon, votre fichier de certificat / clé peut contenir des 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-----

Dans ce cas, il vous incombe de nettoyer la chaîne avant de la transmettre à la configuration de MSAL Node. Exemple :

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

Voir aussi