You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js MSAL认证遇invalid_client错误:证书未注册问题求助

问题:使用MSAL Node获取令牌时持续遇到invalid_client错误(AADSTS700027)

我正在用Node.js搭配MSAL库获取API访问令牌,但一直碰到invalid_client错误。以下是我的代码片段:

import path from 'path';
import fs from 'fs';
import crypto from 'crypto';
import { ConfidentialClientApplication } from '@azure/msal-node'; 
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const clientId = '<MY_CLIENT_ID>';
const tenantId = '<MY_TENANT_ID>';
const thumbprint = '<MY_CERT_THUMBNAIL>';
const scopes = ['.default'];

// Paths to the certificate and key files
const certPath = path.resolve(__dirname, "Cert.crt");
const keyPath = path.resolve(__dirname, "Key.key");

// Read the certificate and private key files
const cert = fs.readFileSync(certPath, 'utf8');
const privateKeySource = fs.readFileSync(keyPath, 'utf8');

// Create the private key object
const privateKeyObject = crypto.createPrivateKey({
    key: privateKeySource,
    format: 'pem'
});

// Export the private key in the required format
const privateKey = privateKeyObject.export({
    format: 'pem',
    type: 'pkcs8'
});

// Remove certificate headers and footers, and encode to base64
const certBase64 = cert
  .replace(/-----BEGIN CERTIFICATE-----/g, '')
  .replace(/-----END CERTIFICATE-----/g, '')
  .replace(/\n/g, '');

// Define the MSAL configuration
const msalConfig = {
  auth: {
      clientId: clientId, 
      authority: `https://login.microsoftonline.com/${tenantId}`, 
      clientCertificate: {
          thumbprint: thumbprint,
          privateKey: privateKey,
          x5c: [certBase64] 
      }
  },
  system: {
      loggerOptions: {
          loggerCallback(loglevel, message, containsPii) {
              console.log(message);
          },
          piiLoggingEnabled: false,
          logLevel: 'Verbose',
      }
  }
};

// Create the confidential client application instance
const cca = new ConfidentialClientApplication(msalConfig);

// Define the client credential request
const clientCredentialRequest = {
  scopes: scopes,
  skipCache: false,
};

// Acquire token by client credential
cca.acquireTokenByClientCredential(clientCredentialRequest)
  .then((response) => {
    console.log("Access token: ", response.accessToken);
  })
  .catch((error) => {
    console.log("Error acquiring token: ", error);
  });

但我一直收到如下错误:

{
  errorCode: 'invalid_client',
  errorMessage: "700027 - [2024-05-31 06:36:17Z]: AADSTS700027: The certificate with identifier used to sign the client assertion is not registered on application. [Reason - The key was not found., Thumbprint of key used by client: '<MY_CERT_THUMBNAIL>', Please visit the Azure Portal, Graph Explorer or directly use MS Graph to see configured keys for app Id '<MY_CLIENT_ID>']. Trace ID: **** Correlation ID: **** Timestamp: 2024-05-31 06:36:17Z - Correlation ID: **** - Trace ID: ****",
  subError: '',
  errorNo: 700027,
  correlationId: '****'
}

我已经检查过Azure门户配置:证书已上传,指纹和代码里的一致,clientId和tenantId也没问题。请问我的代码或配置里可能哪里出问题了?

附加信息

  • Node.js版本:20.0.0
  • @azure/msal-node版本:2.8.1
  • Azure AD应用已配置证书及其指纹
  • 证书已正确上传到Azure AD应用的“Certificates & secrets”选项下

排查方向与解决方案

1. 证书指纹的大小写/格式问题

Azure AD存储的证书指纹为大写无空格格式,检查代码中thumbprint是否存在小写字母或多余空格。比如Azure门户显示A1B2C3D4...,代码里写成a1b2c3d4...就会匹配失败。

2. 私钥与证书不匹配

确保代码中使用的私钥和上传到Azure的证书属于同一密钥对。可以用openssl验证两者模数是否一致:

# 查看证书模数
openssl x509 -in Cert.crt -noout -modulus
# 查看私钥模数
openssl rsa -in Key.key -noout -modulus

若输出的模数不一致,说明两者不是一对,需重新生成密钥对并上传新证书。

3. MSAL配置中x5c字段的处理问题

代码中手动处理证书的逻辑可能有误,MSAL Node会自动处理PEM格式证书,无需手动移除头尾和换行。尝试简化配置:

// 直接读取原始证书文件
const cert = fs.readFileSync(certPath, 'utf8');

const msalConfig = {
  auth: {
      clientId: clientId, 
      authority: `https://login.microsoftonline.com/${tenantId}`, 
      clientCertificate: {
          thumbprint: thumbprint,
          privateKey: privateKey,
          x5c: [cert] // 传入原始PEM格式证书
      }
  },
  // 其他配置不变
};

甚至可以直接省略x5c字段,MSAL会通过指纹匹配Azure中已上传的证书。

4. 私钥格式问题

检查私钥文件是否为未加密的标准PEM格式:

  • 若私钥有密码保护,需在创建私钥对象时添加密码参数:
    const privateKeyObject = crypto.createPrivateKey({
        key: privateKeySource,
        format: 'pem',
        passphrase: '你的私钥密码'
    });
    
  • 确保私钥没有多余注释或格式错误,优先使用PKCS#8格式。

5. Azure AD应用证书状态检查

登录Azure门户,确认证书处于有效状态(未过期),且上传到“Certificates & secrets”下的“Certificates”标签页,而非“Client secrets”标签页。

6. MSAL版本兼容性问题

当前使用的@azure/msal-node 2.8.1版本可能存在证书处理bug,尝试升级到最新稳定版:

npm install @azure/msal-node@latest

内容的提问来源于stack exchange,提问作者Cleanbeans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:28:08