我的项目正在基于.NET Core和System.IdentityModel.Tokens.Jwt
nuget包构建身份验证服务。我们要创建包含公共密钥证书(或证书链)的JWT令牌,这些令牌可用于验证JWT数字签名。商业身份提供商(SaaS)可以做到这一点,并且在JWT规范中通过称为“ x5c”的标头参数来支持。但到目前为止,我一直无法使用它System.IdentityModel.Tokens.Jwt
。
我能够创建使用证书签名的JWT令牌。证书是自签名的,并使用openssl(下面包含的命令)创建。我在C#中的测试代码如下所示:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
// more usings..
public static string GenerateJwtToken(int exampleAccountId, string x509CertFilePath, string x509CertFilePassword)
{
var tokenHandler = new JwtSecurityTokenHandler();
var signingCert = new X509Certificate2(x509CertFilePath, x509CertFilePassword);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, exampleAccountId.ToString()) }),
Expires = DateTime.UtcNow.AddDays(30),
Audience = "myapp:1",
Issuer = "self",
SigningCredentials = new X509SigningCredentials(signingCert, SecurityAlgorithms.RsaSha512Signature),
Claims = new Dictionary<string, object>()
{
["test1"] = "hello world",
["test2"] = new List<int> { 1, 2, 4, 9 }
}
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
生成的令牌头在jwt.io中反序列化为:
{
"alg": "RS512",
"kid": "193A49ED67F22850F4A95258FF07571A985BFCBE",
"x5t": "GTpJ7WfyKFD0qVJY_wdXGphb_L4",
"typ": "JWT"
}
问题是,我也想获取“ x5c”标头参数输出。这样做的原因是,我的项目正在尝试将证书与公钥包括在一起,以验证令牌本身内部的令牌签名,而“ x5c”是实现此目的的好方法。但是我无法使它正常工作。
我尝试使用AdditionalHeaderClaims
on手动添加x5c SecurityTokenDescriptor
,但是令牌中没有输出它。
有人知道该怎么做吗,或者您可以指出一些有关该主题的可靠资源吗?
顺便说一下,这就是我生成使用的证书的方式(在Windows上):
openssl genrsa -out private2048b.key 2048
openssl req -new -key private2048b.key -out myrequest2048.csr -config <path to openssl.cfg>
openssl x509 -req -days 3650 -in myrequest2048.csr -signkey private2048b.key -out public2048b.crt
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in public2048b.crt -inkey private2048b.key -out mypkcs2048.pfx -name "Testtest"
PFX是代码中正在读取和使用的文件。
后代更新
使用Abdulrahman Falyoun的答案,对代码的最后一部分进行了更新,以用于token.Header.Add
在序列化JWT令牌之前手动添加“ x5c”标头参数。令牌必须转换为JwtSecurityToken。这项工作有效,并在https://jwt.io中创建了一个有效的令牌(并具有可以立即验证的签名):
// create JwtSecurityTokenHandler and SecurityTokenDescriptor instance before here..
var exportedCertificate = Convert.ToBase64String(signingCert.Export(X509ContentType.Cert, x509CertFilePassword));
// Add x5c header parameter containing the signing certificate:
var token = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;
token.Header.Add(JwtHeaderParameterNames.X5c, new List<string> { exportedCertificate });
return tokenHandler.WriteToken(token);
什么是x5c?
“ x5c”(X.509证书链)标头参数包含与用于对JWS进行数字签名的密钥相对应的X.509公钥证书或证书链[RFC5280]。证书或证书链表示为证书值字符串的JSON数组。数组中的每个字符串都是以base64编码(不是base64url编码)的DER [ITU.X690.2008] PKIX证书值。包含与用于对JWS进行数字签名的密钥相对应的公用密钥的证书必须是第一证书。可以附加其他证书,随后的每个证书都是用来证明前一个证书的证书。接收者必须根据RFC 5280 [RFC5280]验证证书链,并且如果发生任何验证失败,则认为证书或证书链无效。
注意
从安全角度考虑-不要使用x5c证书直接验证签名。在那种情况下,任何人都可以提供自己的证书并欺骗任何身份。如果x5t / x5t#S256标头用于标识签名者,请检查您是否信任在指定的iss下由x5c或x5t#S256(或其发行者)提供的证书,然后才应验证签名。
所以建立X509链
X509Chain chain = new X509Chain()
bool success = chain.Build(cert);
if (!success) throw Error
然后,对于每个chain.ChainElements
值,使用Certificate属性RawValue
属性(并对其进行base64编码)。
最后,您获得的字符串,x5c
并且应仅将其提供给的标头jwt
。
见以下链接
如何从RSACryptoServiceProvider获取x5c
希望它有用。
如果问题是提供x5c
给标题,则必须使用添加
token.Header.Add(name, value)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句