c# - 在 c# 中使用 ---PUBLIC KEY--- 验证 JWT (ES256) 令牌
问题描述
我有一个由我的 AWS ALB 使用 OpenID 连接器创建的 JWT。我需要在我的 c# 应用程序中验证令牌。但我很难让它发挥作用。
AWS 在此处描述了令牌验证:https ://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html?icmpid=docs_elbv2_console
它应该分三个步骤工作:
- 从令牌中获取密钥 id
- 从 aws alb enpoint 读取公钥
(https://public-keys.auth.elb.' + region + '.amazonaws.com/' + key id)
- 使用密钥解密有效载荷
这是我得到的 JWT:
eyJ0eXAiOiJKV1QiLCJraWQiOiJjODE4ZTcxNi01OTAxLTQzOWQtOWFlZC1lYmRmODAyYjZkYTkiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vc2llbWVucy1xYS0wMDA2OS5ldS5hdXRoMC5jb20vIiwiY2xpZW50IjoiMndsS3k0YlRXbGpZWm9KYXZRSVFqVTE3OUprVG4zNDAiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nOmV1LWNlbnRyYWwtMTo0ODU2ODM0ODcxOTY6bG9hZGJhbGFuY2VyL2FwcC9maW5kLXRlc3QtYWxiLzU3YzBmMWYzZjg0YzZjMjEiLCJleHAiOjE1NzU1NDMwMzN9.eyJzdWIiOiJvYXV0aDJ8bWFpbi10ZW5hbnQtb2lkY3xzYW1scHxTaWVtZW5zfFowMDJFSk5VIiwiZ2l2ZW5fbmFtZSI6IlJhcGhhZWwiLCJmYW1pbHlfbmFtZSI6IlNjaG5haXRsIiwibmlja25hbWUiOiJSYXBoYWVsIiwibmFtZSI6IlJhcGhhZWwgU2NobmFpdGwiLCJwaWN0dXJlIjoiaHR0cHM6Ly9zLmdyYXZhdGFyLmNvbS9hdmF0YXIvODkzNWVlY2QzMDc2ZTAyMTQ5ODE2MTZmZjBkZTRkZjI_cz00ODAmcj1wZyZkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZyYS5wbmciLCJ1cGRhdGVkX2F0IjoiMjAxOS0xMi0wNVQxMDo0ODozMy4wNjhaIiwiZXhwIjoxNTc1NTQzMDMzLCJpc3MiOiJodHRwczovL3NpZW1lbnMtcWEtMDAwNjkuZXUuYXV0aDAuY29tLyJ9.M39aPefXmaDGzaDd0qHcQHMhvugTVN4i4pyvGJ-7fayewU9vZdtKvSzFF9rVal8GEz7HKTr_auqMw9HemOWyag==
因此,密钥 ID 是:c818e716-5901-439d-9aed-ebdf802b6da9
公钥:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENARdEGaEpfgHph3440UodVsQdqxi
PYz+l1aEcz+Bivr6emXDnor1nET94dbPqYxk+vtUHGkgOb44VPEZUe4ijQ==
-----END PUBLIC KEY-----
我尝试使用以下方法验证代码:
- 使用
System.IdentityModel.Tokens.Jwt
命名空间。但是我无法将公钥作为字符串提供给 ValidationParameters。我遵循了这个答案的类似方法https://stackoverflow.com/a/51866939/2250672。感觉很复杂而且容易出错。由于一整天后我无法让它工作,我决定继续使用提供相同功能的 nuget 包之一。 - 使用 JWT nuget 包,但它不支持 AWS ALB 使用的算法。
- 使用 Jose.JWT nuget 包,使用以下代码:
Jose.JWT.Decode(__token, publicKeyPem, Jose.JwsAlgorithm.ES256)
收到以下错误:
错误:脚本执行失败。[ArgumentException] EcdsaUsingSha 算法要求密钥为 CngKey 或 ECDsa 类型。
如何在 C# 中简单地验证来自 AWS ALB 的 JWT?
解决方案
公钥在https://siemens-qa-00069.eu.auth0.com/.well-known/openid-configuration上不可用。因此,您可以尝试手动方法:
private static ECDsa LoadPublicKey(byte[] key)
{
byte[] pubKeyX = key.Skip(27).Take(32).ToArray();
byte[] pubKeyY = key.Skip(59).Take(32).ToArray();
return ECDsa.Create(new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = pubKeyX,
Y = pubKeyY
}
});
}
string key = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENARdEGaEpfgHph3440UodVsQdqxiPYz+l1aEcz+Bivr6emXDnor1nET94dbPqYxk+vtUHGkgOb44VPEZUe4ijQ==";
ECDsa ecdsa = LoadPublicKey(Convert.FromBase64String(key));
string authorizationDomain = "https://siemens-qa-00069.eu.auth0.com/";
string jwt = "eyJ0eXAiOiJKV1QiLCJraWQiOiJjODE4ZTcxNi01OTAxLTQzOWQtOWFlZC1lYmRmODAyYjZkYTkiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vc2llbWVucy1xYS0wMDA2OS5ldS5hdXRoMC5jb20vIiwiY2xpZW50IjoiMndsS3k0YlRXbGpZWm9KYXZRSVFqVTE3OUprVG4zNDAiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nOmV1LWNlbnRyYWwtMTo0ODU2ODM0ODcxOTY6bG9hZGJhbGFuY2VyL2FwcC9maW5kLXRlc3QtYWxiLzU3YzBmMWYzZjg0YzZjMjEiLCJleHAiOjE1NzU1NDMwMzN9.eyJzdWIiOiJvYXV0aDJ8bWFpbi10ZW5hbnQtb2lkY3xzYW1scHxTaWVtZW5zfFowMDJFSk5VIiwiZ2l2ZW5fbmFtZSI6IlJhcGhhZWwiLCJmYW1pbHlfbmFtZSI6IlNjaG5haXRsIiwibmlja25hbWUiOiJSYXBoYWVsIiwibmFtZSI6IlJhcGhhZWwgU2NobmFpdGwiLCJwaWN0dXJlIjoiaHR0cHM6Ly9zLmdyYXZhdGFyLmNvbS9hdmF0YXIvODkzNWVlY2QzMDc2ZTAyMTQ5ODE2MTZmZjBkZTRkZjI_cz00ODAmcj1wZyZkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZyYS5wbmciLCJ1cGRhdGVkX2F0IjoiMjAxOS0xMi0wNVQxMDo0ODozMy4wNjhaIiwiZXhwIjoxNTc1NTQzMDMzLCJpc3MiOiJodHRwczovL3NpZW1lbnMtcWEtMDAwNjkuZXUuYXV0aDAuY29tLyJ9.M39aPefXmaDGzaDd0qHcQHMhvugTVN4i4pyvGJ-7fayewU9vZdtKvSzFF9rVal8GEz7HKTr_auqMw9HemOWyag==";
TokenValidationParameters tokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = authorizationDomain,
ValidateAudience = false,
IssuerSigningKey = new ECDsaSecurityKey(ecdsa)
};
try
{
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
jwtSecurityTokenHandler.ValidateToken(jwt, tokenValidationParameters, out _);
return true;
}
catch (SecurityTokenException)
{
return false;
}
问题是我无法测试它,因为在我的机器上(Windows 10 + .NET Core 2.1)我收到了这个错误:
System.PlatformNotSupportedException:指定的曲线“nistP256”或其参数对此平台无效。---> Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: 参数不正确
推荐阅读
- firebase - Flutter 上的 Firebase 电子邮件和密码注册 - 无法解析主机
- mysql - MySQL | Eloquent - 按第一次出现然后按 ID 排序
- c# - 来自多个列表的 UNION
- reactjs - 在 material-ui 中更改原色会导致 material-ui datepicker 崩溃
- jquery - :eq 在选择第一个时不选择第二个 div | jQuery
- python - python中元组列表的多级排序
- angular - Angular如何在部署更新后刷新站点?
- python - input() 函数没有给出请求
- c# - 如何使用 wrapPanels 在日历中正确显示天数?
- javascript - VueJS - 表示为 2D 数组的 v-model 表