Security 使用System.IdentityModel.Tokens.JWT创建带有x5c头参数的JWT令牌

Security 使用System.IdentityModel.Tokens.JWT创建带有x5c头参数的JWT令牌,security,.net-core,jwt,public-key,x509certificate2,Security,.net Core,Jwt,Public Key,X509certificate2,我的项目是基于.NETCore和System.IdentityModel.Tokens.Jwtnuget包构建一个身份验证服务。我们希望创建包含公钥证书(或证书链)的JWT令牌,该证书可用于验证JWT数字签名。这在商业身份提供者(SaaS)中是可能的,并且在JWT规范中通过称为“x5c”的头参数得到支持。但到目前为止,我无法使用System.IdentityModel.Tokens.Jwt实现这一点 我能够创建使用证书签名的JWT令牌。证书是使用openssl(下面包含的命令)自签名和创建的。

我的项目是基于.NETCore和
System.IdentityModel.Tokens.Jwt
nuget包构建一个身份验证服务。我们希望创建包含公钥证书(或证书链)的JWT令牌,该证书可用于验证JWT数字签名。这在商业身份提供者(SaaS)中是可能的,并且在JWT规范中通过称为“x5c”的头参数得到支持。但到目前为止,我无法使用
System.IdentityModel.Tokens.Jwt
实现这一点

我能够创建使用证书签名的JWT令牌。证书是使用openssl(下面包含的命令)自签名和创建的。 我在C#中的测试代码如下所示:

使用Microsoft.IdentityModel.Tokens;
使用System.IdentityModel.Tokens.Jwt;
//更多的用法。。
公共静态字符串GenerateJwtToken(int-exampleAccountId、字符串x509CertFilePath、字符串x509CertFilePassword)
{
var tokenHandler=new JwtSecurityTokenHandler();
var signingCert=新的X509Certificate2(x509CertFilePath,x509CertFilePassword);
var tokenDescriptor=新的SecurityTokenDescriptor
{
Subject=newclaimsidentity(new[]{newclaim(ClaimTypes.Name,exampleAccountId.ToString())}),
Expires=DateTime.UtcNow.AddDays(30),
受众=“myapp:1”,
发卡机构=“自我”,
SigningCredentials=新的X509 SigningCredentials(signingCert、SecurityAlgorithms.rsasha512签名),
索赔=新词典()
{
[“test1”]=“你好,世界”,
[“test2”]=新列表{1,2,4,9}
}
};
var token=tokenHandler.CreateToken(tokenDescriptor);
返回tokenHandler.WriteToken(令牌);
}
生成的令牌头在jwt.io中反序列化为:

{
“alg”:“RS512”,
“儿童”:“193A49ED67F22850F4A95258FF07571A985BFCBE”,
“x5t”:“GTpJ7WfyKFD0qVJY_wdXGphb_L4”,
“典型”:“JWT”
}
问题是,我也想得到“x5c”头参数输出。这样做的原因是我的项目正在尝试使用公钥包含证书,以验证令牌本身内部的令牌签名,而“x5c”是一种很好的方法。但我就是不能让它工作

我曾尝试在
SecurityTokenDescriptor
上使用
AdditionalHeaderClaims
手动添加x5c,但它只是没有在令牌中输出

有人知道怎么做吗,或者你能给我指一些关于这个主题的可靠资源吗

顺便说一下,这就是我如何生成所使用的证书(在Windows上):


什么是x5c?

“x5c”(X.509证书链)头参数包含与用于对JWS进行数字签名的密钥相对应的X.509公钥证书或证书链[RFC5280]。证书或证书链表示为证书值字符串的JSON数组。数组中的每个字符串都是[ITU.X690.2008]PKIX证书值的base64编码(不是base64url编码)。包含与用于对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.chainements
value,获取证书属性
RawValue
属性(并对其进行base64编码)

最后,您得到了
x5c
的字符串,应该只将其提供给
jwt
的头

请参阅以下链接

希望有用

#编辑 如果问题是向标头提供
x5c
,则必须使用

token.Header.Add(name, value)

我很感谢您所做的努力,但问题并不在于创建证书链。它是关于让System.IdentityModel.Tokens.Jwt nuget包(特别是
JwtSecurityTokenHandler
类)输出包含x5c header参数的Jwt令牌,而不是仅输出x5t header参数。我将更新问题以更清楚地了解这一点。
SecurityTokenDescriptor.Claims
SecurityTokenDescriptor.AdditionalHeaderClaims
当前仅由
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.
在安装
System.IdentityModel.Tokens.Jwt
nuget时支持包中,您还可以获得
Microsoft.IdentityModel.Tokens
,这样您就可以将
SecurityTokenDescriptor
类与
JwtSecurityTokenHandler
类一起使用。在
SecurityTokenDescriptor.AdditionalHeaderClaims
中手动添加x5c似乎是正确的做法,但不幸的是,“x5c”没有被输出。似乎JwtSecurityTokenHandler只是忽略了它。很抱歉没有提供任何帮助您建议使用
token.Header.Add(…)
(现在已删除)太棒了!这解决了整个问题!如果您可以使用此代码片段更新您的答案,那么我将授予您奖金:
token.Header.Add(name, value)