如何使用PEM格式证书生成Azure Active Directory应用访问令牌
基于PEM格式证书生成Azure AD访问令牌的实现方法
核心逻辑不需要改动原有令牌获取流程,问题根源是PEM格式通常拆分存储公钥证书和私钥,无法像自包含私钥的PFX格式一样直接加载为可用的X509Certificate2实例,只要正确生成带关联私钥的X509Certificate2对象,就能复用原有的令牌生成代码。
正确生成带私钥的X509Certificate2实例
PEM格式文件一般包含两类内容:
- 带
-----BEGIN CERTIFICATE-----标识的X509公钥证书内容 - 带
-----BEGIN PRIVATE KEY-----标识的对应私钥内容
.NET 5及以上版本的简化实现
直接使用内置方法加载PEM内容生成证书,无需手动转码:
// 读取本地存储的PEM格式公钥、私钥文件内容 var certPemContent = await File.ReadAllTextAsync(credentialConfigOptions.CertificatePemPath); var privateKeyPemContent = await File.ReadAllTextAsync(credentialConfigOptions.PrivateKeyPemPath); // 内存中生成绑定了私钥的证书实例 var certificate = X509Certificate2.CreateFromPem(certPemContent, privateKeyPemContent);
如果私钥设置了访问密码,可使用带密码参数的重载完成加载。
.NET Core 3.1及更早版本的兼容实现
低版本.NET没有内置PEM解析方法,需要手动完成内容解码和私钥关联:
// 解析公钥证书部分,生成基础证书实例 var certPemRaw = new string(certPemContent.Where(c => !char.IsWhiteSpace(c)).ToArray()) .Replace("-----BEGIN CERTIFICATE-----", string.Empty) .Replace("-----END CERTIFICATE-----", string.Empty); var certDerBytes = Convert.FromBase64String(certPemRaw); var certificate = new X509Certificate2(certDerBytes); // 解析私钥部分 var privateKeyPemRaw = new string(privateKeyPemContent.Where(c => !char.IsWhiteSpace(c)).ToArray()) .Replace("-----BEGIN PRIVATE KEY-----", string.Empty) .Replace("-----END PRIVATE KEY-----", string.Empty); var privateKeyDerBytes = Convert.FromBase64String(privateKeyPemRaw); var rsaKey = RSA.Create(); rsaKey.ImportPkcs8PrivateKey(privateKeyDerBytes, out _); // 将私钥与证书实例绑定 certificate = certificate.CopyWithPrivateKey(rsaKey);
替换原有证书加载逻辑,复用现有令牌生成流程
将之前从Windows证书存储读取PFX证书的代码,替换为上述步骤生成的X509Certificate2实例,后续的ClientAssertionCertificate初始化、AcquireTokenAsync调用完全无需调整,替换后的完整逻辑如下:
var authority = string.Format(authorityUri, credentialConfigOptions.TenantId); var authContext = new AuthenticationContext(authority); // 此处替换原有证书存储读取逻辑,加载PEM格式生成的带私钥证书实例 var certificate = X509Certificate2.CreateFromPem(certPemContent, privateKeyPemContent); var clientAssertionCertificate = new ClientAssertionCertificate(credentialConfigOptions.AppId, certificate); AuthenticationResult token = await authContext.AcquireTokenAsync(appId, clientAssertionCertificate); return token?.AccessToken;
常见踩坑说明
- 仅加载PEM中公钥部分、未关联对应私钥的证书实例,会在令牌签名阶段报
Keyset does not exist类错误,必须确保证书实例绑定了可用的私钥 - 跨平台部署在Linux环境时,无需将PEM转换为PFX格式再写入系统证书存储,内存中绑定私钥的证书实例可直接完成Azure AD的签名验证流程
- 无需手动导出PFX做二次加载,部分低版本.NET在跨平台场景下导出PFX会出现私钥丢失的问题,直接使用内存中生成的证书实例即可
内容的提问来源于stack exchange,提问作者Amit Agrawal
相关产品推荐
相关产品推荐

