繁体   English   中英

在 msal-node js 中使用带有证书的 SPN 获取访问令牌的 azure 活动目录面临错误“ERR_OSSL_PEM_NO_START_LINE”

[英]azure active directory get access token using SPN with certificate in msal-node js facing error "ERR_OSSL_PEM_NO_START_LINE "

我正在尝试使用 msal 节点从 azure 获取访问令牌,并且需要遵循带有证书的服务原则。 目前我正在使用密钥保管库 url 来读取证书。 我的参考文档是https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/samples/msal-node-samples/auth-code-key-vault/index.js

const msal = require('@azure/msal-node');
const { DefaultAzureCredential } = require('@azure/identity');
const { CertificateClient } = require('@azure/keyvault-certificates');
const { SecretClient } = require('@azure/keyvault-secrets');

const getazureToken = async () => {
  const credential = new DefaultAzureCredential();
  const client = new CertificateClient(config.keyVaultUrl, credential);
  const secretClient = new SecretClient(config.keyVaultUrl, credential);
  const certResponse = await client.getCertificate(config.certificateName);
  const thumbprint = certResponse.properties.x509Thumbprint.toString('hex');
  const secretResponse = await secretClient.getSecret(config.certificateName);
  const privateKey = secretResponse.value;
  await msalApp(thumbprint, privateKey);
};

async function msalApp(thumbprint, privateKey) {
  // Before running the sample, you will need to replace the values in the config
  const msalConfig = {
    auth: {
      clientId: config.azureClientId,
      authority: `${config.authorityUri}${config.tenantId}/`,
      clientCertificate: {
        thumbprint,
        privateKey,
      },
    },
    system: {
      loggerOptions: {
        loggerCallback(loglevel, message, containsPii) {
          console.log('loglevel', loglevel, message);
        },
        piiLoggingEnabled: false,
        logLevel: msal.LogLevel.Verbose,
      },
    },
  };

  // Create msal application object
  const cca = new msal.ConfidentialClientApplication(msalConfig);
  const authCodeUrlParameters = {
    scopes: config.scope,
  };

  cca
    .acquireTokenByClientCredential(authCodeUrlParameters)
    .then((response) => {
      console.log('==========> response', response);
    })
    .catch((error) =>
      console.log('error------------->', JSON.stringify(error))
    );
}

错误: 在此处输入图片说明

我也有证书的 .pfx 文件。 如果有帮助的话。

解决方案是您可以使用以下代码从证书的 .pfx 文件中提取 .pem 文件

const forge = require('node-forge');
const fs = require('fs');

const convertPfxToPem = async (keyFile, passphrase) => {
  const keyBase64 = keyFile.toString('base64');
  const p12Der = forge.util.decode64(keyBase64);
  const asn = forge.asn1.fromDer(p12Der);
  const p12 = forge.pkcs12.pkcs12FromAsn1(asn, false, 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]
    );

  // 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);
  fs.writeFileSync('key.pem', privateKey);

  return {
    key: privateKey,
  };
};

现在读取 .pfx 文件并存储 key.pem 并使用它。

 let key = null;
    if (fs.existsSync(path.resolve(__dirname, '../key.pem'))) {
       key = fs.readFileSync(path.resolve(__dirname, '../key.pem'));
    } else {
       const pemResponse = await convertPfxToPem(
       fs.readFileSync(path.resolve(__dirname, '../certificate.pfx')),
       config.passphrase
       );
       key = pemResponse.key;
    }

和 getazureToken 如下所示

const credential = new DefaultAzureCredential();
  const client = new CertificateClient(config.keyVaultUrl, credential);
  const certResponse = await client.getCertificate(config.certificateName);
  const thumbprint = certResponse.properties.x509Thumbprint.toString('hex');
  let key = null;
  if (fs.existsSync(path.resolve(__dirname, '../key.pem'))) {
    key = fs.readFileSync(path.resolve(__dirname, '../key.pem'));
  } else {
    const pemResponse = await convertPfxToPem(
      fs.readFileSync(path.resolve(__dirname, '../certificate.pfx')),
      config.passphrase
    );
    key = pemResponse.key;
  }
  try {
    const tokenResponse = await msalApp(thumbprint, key);
    return tokenResponse;
  } catch (err) {}

当我们尝试以 pem 格式上传的证书格式不正确时,可能会发生此错误。

请在Pem.js文件中检查您的证书格式。 请确认pem文件的内容ie; 证书字符串和私钥字符串具有以下格式:这意味着用行包围密钥,包括 BEGIN / END CERTIFICATE 前后的 5 个连字符,每个连字符在不同的行中。 像下面这样

-----开始私钥-----\\nLONG_STRING_HERE\\n-----结束私钥-----

(检查是否遗漏了任何字符或连字符)您可以在此处检查您的证书,然后尝试删除(空格)ie; 在 BEGIN / END CERTIFICATE 之后和之前的“\\s”,并将它们替换为来自证书正则表达式和来自 pem.js 文件的私钥正则表达式的新行“\\n”,借助已经涉及的函数或相应地手动修改。

请检查https://github.com/auth0/node-jsonwebtoken/issues/642#issuecomment

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM