Skip to content

Latest commit

 

History

History
270 lines (185 loc) · 13.2 KB

how-to-web-app-node-use-certificate.md

File metadata and controls

270 lines (185 loc) · 13.2 KB
title description author manager ms.author ms.service ms.subservice ms.topic ms.date ms.custom
Use client certificate for authentication in your Node.js web app
Learn how to use client certificate instead of secrets for authentication in your Node.js web app
kengaderdus
mwongerapk
kengaderdus
entra-external-id
customers
how-to
01/27/2024
developer, devx-track-js

Use client certificate for authentication in your Node.js web app

Microsoft Entra External ID supports two types of authentication for confidential client applications; password-based authentication (such as client secret) and certificate-based authentication. For a higher level of security, we recommend using a certificate (instead of a client secret) as a credential in your confidential client applications.

In production, you should purchase a certificate signed by a well-known certificate authority, and use Azure Key Vault to manage certificate access and lifetime for you. However, for testing purposes, you can create a self-signed certificate and configure your apps to authenticate with it.

In this article, you learn to generate a self-signed certificate by using Azure Key Vault on the Azure portal, OpenSSL, or PowerShell. If you have a client secret already, you'll learn how to safely delete it.

When needed, you can also create a self-signed certificate programmatically by using .NET, Node.js, Go, Python or Java client libraries.

Prerequisites

Create a self-signed certificate

If you have an existing self-signed certificate in your local computer, you can skip this step, then proceed to Upload certificate to your app registration.

You can use Azure Key Vault to generate a self-signed certificate for your app. By using Azure Key Vault, you enjoy benefits, such as, assigning a partner Certificate Authority (CA) and automating certificate rotation.

If you have an existing self-signed certificate in Azure Key Vault, and you want to use it without downloading it, skip this step, then proceed to Use a self-signed certificate directly from Azure Key Vault. Otherwise, use the following steps to generate your certificate

  1. Follow the steps in Set and retrieve a certificate from Azure Key Vault using the Azure portal to create and download your certificate.

  2. After you create your certificate, download both the .cer file and the .pfx file such as ciam-client-app-cert.cer and ciam-client-app-cert.pfx. The .cer file contains the public key and is what you upload to your Microsoft Entra admin center.

  3. In your terminal, run the following command to extract the private key from the .pfx file. When prompted to type a pass phrase, just press Enter key you if you don't want to set one. Otherwise type a pass phrase of your choice:

    openssl pkcs12 -in ciam-client-app-cert.pfx -nocerts -out ciam-client-app-cert.key

    The ciam-client-app-cert.key file is what you use in your app.

  1. Use the steps in Create a self-signed public certificate to authenticate your application. Make sure you export your public certificate with its private key. For the certificateName, use ciam-client-app-cert.

  2. In your terminal, run the following command to extract the private key from the .pfx file. When prompted to type in your pass phrase, type a pass phrase of your choice:

    openssl pkcs12 -in ciam-client-app-cert.pfx -nocerts -out ciam-client-app-cert.key

After you complete these steps, you should have a .cer file and the .key file, such as ciam-client-app-cert.key and ciam-client-app-cert.cer. The .key file is what you use in your app. The .cer file is what you upload to your Microsoft Entra admin center.

In your terminal, run the following command. When prompted to type in your pass phrase, type a pass phrase of your choice:

openssl req -x509 -newkey rsa:2048 -keyout ciam-client-app-cert.key -out ciam-client-app-cert.crt -subj "/CN=ciamclientappcert.com"

After the command finishes execution, you should have a .crt and a .key files, such as ciam-client-app-cert.key and ciam-client-app-cert.crt. The .key file is what you use in your app. The .cer file is what you upload to your Microsoft Entra admin center.


Upload certificate to your app registration

[!INCLUDE active-directory-customers-app-integration-add-user-flow]

[!INCLUDE remove-client-secret]

Configure your Node.js app to use certificate

Once you associate your app registration with the certificate, you need to update your app code to start using the certificate:

  1. Locate the file that contains your MSAL configuration object, such as msalConfig in authConfig.js, then update it to look similar to the following code. If you have a client secret present, make sure you remove it:

    require('dotenv').config();
    const fs = require('fs'); //// import the fs module for reading the key file
    const crypto = require('crypto');
    const TENANT_SUBDOMAIN = process.env.TENANT_SUBDOMAIN || 'Enter_the_Tenant_Subdomain_Here';
    const REDIRECT_URI = process.env.REDIRECT_URI || 'http://localhost:3000/auth/redirect';
    const POST_LOGOUT_REDIRECT_URI = process.env.POST_LOGOUT_REDIRECT_URI || 'http://localhost:3000';
    
    const privateKeySource = fs.readFileSync('PATH_TO_YOUR_PRIVATE_KEY_FILE')
    
    const privateKeyObject = crypto.createPrivateKey({
        key: privateKeySource,
        passphrase: 'Add_Passphrase_Here',
        format: 'pem'
    });
    
    const privateKey = privateKeyObject.export({
        format: 'pem',
        type: 'pkcs8'
    });
    
    /**
     * Configuration object to be passed to MSAL instance on creation.
     * For a full list of MSAL Node configuration parameters, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
     */
        const msalConfig = {
            auth: {
                clientId: process.env.CLIENT_ID || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
                authority: process.env.AUTHORITY || `https://${TENANT_SUBDOMAIN}.ciamlogin.com/`, 
                clientCertificate: {
                    thumbprint: "YOUR_CERT_THUMBPRINT", // replace with thumbprint obtained during step 2 above
                    privateKey: privateKey
                }
            },
            //... Rest of code in the msalConfig object
        };
    
    module.exports = {
        msalConfig,
        REDIRECT_URI,
        POST_LOGOUT_REDIRECT_URI,
        TENANT_SUBDOMAIN
    };

    In your code, replace the placeholders:

    • Add_Passphrase_Here with the pass phrase you used to encrypt your private key.

    • YOUR_CERT_THUMBPRINT with the Thumbprint value you recorded earlier.

    • PATH_TO_YOUR_PRIVATE_KEY_FILE with the file path to your private key file.

    • Enter_the_Application_Id_Here with the Application (client) ID of the app you registered earlier.

    • Enter_the_Tenant_Subdomain_Here and replace it with the Directory (tenant) subdomain. For example, if your tenant primary domain is contoso.onmicrosoft.com, use contoso. If you don't have your tenant name, learn how to read your tenant details.

    We encrypted the key (we recommend that you do so), so we have to decrypt it before we pass it to MSAL configuration object.

    //...
    const privateKeyObject = crypto.createPrivateKey({
        key: privateKeySource,
        passphrase: 'Add_Passphrase_Here',
        format: 'pem'
    });
    
    const privateKey = privateKeyObject.export({
        format: 'pem',
        type: 'pkcs8'
    });
    //...
  2. Use the steps in Run and test the web app to test your app.

Use a self-signed certificate directly from Azure Key Vault

You can use your existing certificate directly from Azure Key Vault:

  1. Locate the file that contains your MSAL configuration object, such as msalConfig in authConfig.js, then remove the clientSecret property:

    const msalConfig = {
        auth: {
            clientId: process.env.CLIENT_ID || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
            authority: process.env.AUTHORITY || `https://${TENANT_SUBDOMAIN}.ciamlogin.com/`, 
        },
        //...
    };
  2. Install Azure CLI, then on your console, type the following command to sign-in:

    az login --tenant YOUR_TENANT_ID

    Replace the placeholder YOUR_TENANT_ID with the Directory (tenant) ID you copied earlier.

  3. On your console, type the following command to install the required packages:

    npm install --save @azure/identity @azure/keyvault-certificates @azure/keyvault-secrets
  4. In your client app, use the following code to generate thumbprint and privateKey;

    const identity = require("@azure/identity");
    const keyvaultCert = require("@azure/keyvault-certificates");
    const keyvaultSecret = require('@azure/keyvault-secrets');
    
    const KV_URL = process.env["KEY_VAULT_URL"] || "ENTER_YOUR_KEY_VAULT_URL"
    const CERTIFICATE_NAME = process.env["CERTIFICATE_NAME"] || "ENTER_THE_NAME_OF_YOUR_CERTIFICATE_ON_KEY_VAULT";
    
    // Initialize Azure SDKs
    const credential = new identity.DefaultAzureCredential();
    const certClient = new keyvaultCert.CertificateClient(KV_URL, credential);
    const secretClient = new keyvaultSecret.SecretClient(KV_URL, credential);
    
    async function getKeyAndThumbprint() {
    
        // Grab the certificate thumbprint
        const certResponse = await certClient.getCertificate(CERTIFICATE_NAME).catch(err => console.log(err));
        const thumbprint = certResponse.properties.x509Thumbprint.toString('hex')
    
        // When you upload a certificate to Key Vault, a secret containing your private key is automatically created
        const secretResponse = await secretClient.getSecret(CERTIFICATE_NAME).catch(err => console.log(err));;
    
        // secretResponse contains both public and private key, but we only need the private key
        const privateKey = secretResponse.value.split('-----BEGIN CERTIFICATE-----\n')[0]
    }
    
    getKeyAndThumbprint();        

    In your code, replace the placeholders:

    • ENTER_YOUR_KEY_VAULT_URL with your Azure Key Vault URL.

    • ENTER_THE_NAME_OF_YOUR_CERTIFICATE_ON_KEY_VAULT with the name of your certificate in Azure Key Vault.

  5. Use the thumbprint and privateKey values to update your configuration:

    let clientCert = {
        thumbprint: thumbprint, 
        privateKey: privateKey,
    };
    
    msalConfig.auth.clientCertificate = clientCert; //For this to work, you can't declares your msalConfig using const modifier 
  6. Then proceed to instantiate your confidential client as shown in the getMsalInstance method:

    class AuthProvider {
        //...
        getMsalInstance(msalConfig) {
            return new msal.ConfidentialClientApplication(msalConfig);
        }
        //...
    }
  7. Use the steps in Run and test the web app to test your app.

Next steps

Learn how to: