C# 在c中使用---公钥---验证JWT(ES256)令牌#

C# 在c中使用---公钥---验证JWT(ES256)令牌#,c#,amazon-web-services,jwt,openid-connect,C#,Amazon Web Services,Jwt,Openid Connect,我有一个JWT,它是由我的AWS ALB使用OpenID连接器创建的。我需要在我的c#应用程序中验证令牌。但我努力让它工作 AWS在此处描述了令牌验证: 它应分为3个步骤: 从令牌获取密钥id 从aws alb enpoint读取公钥(https://public-keys.auth.elb.“+region+”.amazonaws.com/“+key-id) 使用密钥解密有效负载 这是我得到的JWT: 在这一方面,我们的研究工作是一个关于未来的未来的未来的未来的未来的未来的未来的未来的未来

我有一个JWT,它是由我的AWS ALB使用OpenID连接器创建的。我需要在我的c#应用程序中验证令牌。但我努力让它工作

AWS在此处描述了令牌验证:

它应分为3个步骤:

  • 从令牌获取密钥id
  • 从aws alb enpoint读取公钥
    (https://public-keys.auth.elb.“+region+”.amazonaws.com/“+key-id)
  • 使用密钥解密有效负载
这是我得到的JWT:

在这一方面,我们的研究工作是一个关于未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的未来的Z2.在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,在中国,MZJBKZTRKZJI_cz00ODAMCJ1WZYZKPH0DHBZJTNBJJJJJJJY2RULMF1DGGWLmbShuyrmKZYYS5WBMCIlCJ1CGRHDGVKX2F0IjOijAxOxMI0WnVqxM0Odozmy4WnJHaiwizHjJJJJJJJJZMjY2RULf1dGwLbWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnJ9.9PnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnWnW==

因此,密钥id是:
c818e716-5901-439d-9aed-ebdf802b6da9

公钥:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENARdEGaEpfgHph3440UodVsQdqxi
PYz+l1aEcz+Bivr6emXDnor1nET94dbPqYxk+vtUHGkgOb44VPEZUe4ijQ==
-----END PUBLIC KEY-----
我尝试使用以下方法验证代码:

  • 使用
    System.IdentityModel.Tokens.Jwt
    命名空间。但我无法将公钥作为字符串提供给ValidationParameters。我采用了类似的方法来回答这个问题。它感觉复杂而且容易出错。由于我一整天都无法让它工作,我决定继续使用提供相同功能的nuget软件包
  • 使用JWT nuget包,但不支持AWS ALB使用的算法
  • 使用以下代码使用Jose.JWT nuget包:
Jose.JWT.Decode(uu令牌,publicKeyPem,Jose.JwsAlgorithm.ES256)

获取以下错误:

错误:脚本执行失败。[ArgumentException]EcdsaUsingSha算法要求密钥为CngKey或ECDsa类型


如何在C#中简单地验证AWS ALB中的JWT?

公钥在上不可用。因此,您可以尝试手动方法:

    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
            }
        });
    }

问题是我无法测试它,因为在我的机器(Windows 10+.NET Core 2.1)上,我遇到以下错误:

System.PlatformNotSupportedException:指定的曲线“nistP256”或其参数对此平台无效。-->Internal.Cryptography.CryptothWherPer+WindowsCryptographyException:参数不正确


您的JWT由
https://siemens-qa-00069.eu.auth0.com/
。为什么要根据AWS密钥验证它?因为JWT是由AWS负载平衡器生成的。您如何解释JWT具有
https://siemens-qa-00069.eu.auth0.com/
作为发行人?我想验证签名人,在jwt中被称为签名人,“签名人”:“arn:aws:elasticloadbalancement:eu-central-1:485683487196:loadbalancer/app/find test alb/57c0f1f3f84c6c21”。这就是我尝试根据aws密钥验证它的原因。如果您尝试在jwt.io上使用公钥,您将看到它是有效的。(您需要从签名中删除尾随的
=
)您的代码返回false,您是否尝试验证我提供的令牌?ECDSA创建为我指明了正确的方向,但我使用bouncy castle
PemReader
获取X/Y坐标(它们的长度为32字节,而不是45字节)。以下坐标对我有效:Q=new ECPoint{X=bytes.Skip(27).Take(32).ToArray(),//ecPublicKeyParameters.Q.XCoord.GetEncoded(),Y=bytes.Skip(59).Take(32).ToArray()//ecPublicKeyParameters.Q.YCoord.GetEncoded(),});我根据您的发现修改了答案。感谢您对使用.NET Core的Windows 10的反馈。如果您的曲线参数不正确,您将获得PlatformNotSupportedException。
        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;
        }