Node.js Web アプリでの認証にクライアント証明書を使用する
適用対象: 従業員テナント 外部テナント (詳細情報)
Microsoft Entra 外部 ID では、機密クライアント アプリケーション用に、パスワードベースの認証 (クライアント シークレットなど) と証明書ベースの認証の 2 種類の認証がサポートされています。 より高いレベルのセキュリティを実現するには、機密クライアント アプリケーションで (クライアント シークレットではなく) 証明書を資格情報として使用することをお勧めします。
運用環境では、既知の証明機関によって署名された証明書を購入し、Azure Key Vaultを使用して証明書のアクセスと有効期間を管理する必要があります。 ただし、テストの目的で自己署名証明書を作成し、これを使って認証するようにアプリを構成できます。
この記事では、Azure portal、OpenSSL、または PowerShell 上で Azure Key Vault を使って自己署名証明書を生成する方法について説明します。 クライアント シークレットが既にある場合は、それを安全に削除する方法について説明します。
必要に応じて、.NET、Node.js、Go、Python、または Java の各クライアント ライブラリを使用して、プログラムで自己署名証明書を作成することもできます。
前提条件
Visual Studio Code、または別のコード エディター。
外部テナント。 お持ちでない場合は、無料試用版にサインアップしてください。
OpenSSL。Chocolatey を使用して簡単に OpenSSL を Windows にインストールできます。
Windows PowerShell または Azure サブスクリプション。
自己署名証明書を作成する
ローカル コンピューターに既存の自己署名証明書がある場合は、この手順をスキップして、「アプリ登録に証明書をアップロードする」に進んでください。
Azure Key Vaultを使用して、アプリの自己署名証明書を生成できます。 Azure Key Vault を使用すると、パートナー証明機関 (CA) の割り当てや証明書ローテーションの自動化などの利点があります。
Azure Key Vault に既存の自己署名証明書があり、それをダウンロードせずに使用する場合は、この手順をスキップして、「Azure Key Vault から自己署名証明書を直接使用する」に進んでください。 それ以外の場合は、次の手順に従って証明書を生成します
「Azure portal を使用して Azure Key Vault から証明書の設定と取得を行う」の手順に従って、証明書を作成してダウンロードします。
証明書を作成したら、.cer ファイルと .pfx ファイルの両方 (ciam-client-app-cert.cer と ciam-client-app-cert.pfx など) をダウンロードします。 .cer ファイルには公開キーが含まれています。これを、Microsoft Entra 管理センターにアップロードします。
ターミナルで次のコマンドを実行して、.pfx ファイルから秘密キーを抽出します。 パス フレーズを入力するように求められたときに、パス フレーズを設定しない場合は、Enter キーを押します。 それ以外の場合は、任意のパス フレーズを入力します。
openssl pkcs12 -in ciam-client-app-cert.pfx -nocerts -out ciam-client-app-cert.key
ciam-client-app-cert.key ファイルは、アプリで使用するファイルです。
アプリ登録に証明書をアップロードする
クライアント アプリ証明書を使用するには、Microsoft Entra 管理センターで登録したアプリを証明書に関連付ける必要があります。
アプリケーション管理者以上の権限で Microsoft Entra 管理センターにサインインします。
複数のテナントにアクセスできる場合、上部のメニューの [設定] アイコン を使用し、[ディレクトリとサブスクリプション] メニューから外部テナントに切り替えます。
[ID]>[アプリケーション]>[アプリの登録] を参照します。
アプリ登録の一覧から、証明書に関連付けるアプリ ( ciam-client-app など) を選択します。
[管理] で、[証明書とシークレット] を選択します。
[証明書] を選択してから、[証明書のアップロード] を選択します。
[Select a file](ファイルの選択) ファイル アイコンを選択してから、アップロードする証明書 (ciam-client-app-cert.pem、ciam-client-app-cert.cer、ciam-client-app-cert.crt など) を選択します。
[説明] に、”CIAM クライアント アプリ証明書” などの説明を入力し、[追加] を選択して証明書をアップロードします。 証明書がアップロードされると、[拇印]、[開始日]、[有効期限] の値が表示されます。
後でクライアント アプリを構成するときに使用できるように、[拇印] の値を記録します。
アプリケーション用のクライアント シークレットが既に用意されている場合は、アプリケーションを偽装する悪意のあるアプリケーションを回避するために、それを削除する必要があります。
- [クライアント シークレット] タブに移動して、[削除] アイコンを選びます。
- 表示されるポップアップ ウィンドウで、[はい] を選びます。
証明書を使用するように Node.js アプリを構成する
アプリの登録を証明書に関連付けたら、証明書の使用を開始するようにアプリ コードを更新する必要があります。
authConfig.js の
msalConfig
など、MSAL 構成オブジェクトが含まれるファイルを見つけて、次のコードのように更新します。 クライアント シークレットが存在する場合は、必ずそれを削除します。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 };
コードで、次のプレースホルダーを置き換えます。
Add_Passphrase_Here
を、秘密キーの暗号化に使用したパス フレーズに置き換えます。YOUR_CERT_THUMBPRINT
を、先ほど記録した 拇印の値に置き換えます。PATH_TO_YOUR_PRIVATE_KEY_FILE
を、秘密キー ファイルへのファイル パスに置き換えます。Enter_the_Application_Id_Here
を、前に登録したアプリのアプリケーション (クライアント) ID に置き換えます。Enter_the_Tenant_Subdomain_Here
を、ディレクトリ (テナント) サブドメインに置き換えます。 たとえば、テナントのプライマリ ドメインがcontoso.onmicrosoft.com
の場合は、contoso
を使用します。 テナント名がない場合は、テナントの詳細を読み取る方法を確認してください。
ここではキーを暗号化 (推奨) したので 、MSAL 構成オブジェクトに渡す前に暗号化を解除する必要があります。
//... const privateKeyObject = crypto.createPrivateKey({ key: privateKeySource, passphrase: 'Add_Passphrase_Here', format: 'pem' }); const privateKey = privateKeyObject.export({ format: 'pem', type: 'pkcs8' }); //...
「Web アプリを実行してテストする」の手順を使用して、アプリをテストします。
Azure Key Vault から自己署名証明書を直接使用する
次のように、既存の証明書を Azure Key Vault から直接使用できます。
authConfig.js の
msalConfig
など、MSAL 構成オブジェクトが含まれるファイルを見つけて、clientSecret
プロパティを削除します。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/`, }, //... };
Azure CLI をインストールし、コンソールで次のコマンドを入力してサインインします。
az login --tenant YOUR_TENANT_ID
プレースホルダー
YOUR_TENANT_ID
を、、前にコピーしたディレクトリ (テナント) ID に置き換えます。コンソールで次のコマンドを入力して、必要なパッケージをインストールします。
npm install --save @azure/identity @azure/keyvault-certificates @azure/keyvault-secrets
クライアント アプリで、次のコードを使用して
thumbprint
と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();
コードで、次のプレースホルダーを置き換えます。
ENTER_YOUR_KEY_VAULT_URL
を実際の Azure Key Vault の URL に置き換えます。ENTER_THE_NAME_OF_YOUR_CERTIFICATE_ON_KEY_VAULT
を、Azure Key Vault 内の証明書の名前に置き換えます。
thumbprint
とprivateKey
の値を使用して構成を更新します。let clientCert = { thumbprint: thumbprint, privateKey: privateKey, }; msalConfig.auth.clientCertificate = clientCert; //For this to work, you can't declares your msalConfig using const modifier
次に、
getMsalInstance
メソッドに示すように、機密クライアントのインスタンス化に進みます。class AuthProvider { //... getMsalInstance(msalConfig) { return new msal.ConfidentialClientApplication(msalConfig); } //... }
「Web アプリを実行してテストする」の手順を使用して、アプリをテストします。
次のステップ
具体的には、次の方法を学習します。