5

I have got a JWT that is created by my AWS ALB using an OpenID Connector. I need to verify the Token in my c# application. But I struggle to get it working.

AWS describes the token validation here: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html?icmpid=docs_elbv2_console

It should work in 3 steps:

  • Get the key id from the token
  • Read the public key from the aws alb enpoint (https://public-keys.auth.elb.' + region + '.amazonaws.com/' + key id)
  • Decrypt the payload using the key

This is the JWT I got:

eyJ0eXAiOiJKV1QiLCJraWQiOiJjODE4ZTcxNi01OTAxLTQzOWQtOWFlZC1lYmRmODAyYjZkYTkiLCJhbGciOiJFUzI1NiIsImlzcyI6Imh0dHBzOi8vc2llbWVucy1xYS0wMDA2OS5ldS5hdXRoMC5jb20vIiwiY2xpZW50IjoiMndsS3k0YlRXbGpZWm9KYXZRSVFqVTE3OUprVG4zNDAiLCJzaWduZXIiOiJhcm46YXdzOmVsYXN0aWNsb2FkYmFsYW5jaW5nOmV1LWNlbnRyYWwtMTo0ODU2ODM0ODcxOTY6bG9hZGJhbGFuY2VyL2FwcC9maW5kLXRlc3QtYWxiLzU3YzBmMWYzZjg0YzZjMjEiLCJleHAiOjE1NzU1NDMwMzN9.eyJzdWIiOiJvYXV0aDJ8bWFpbi10ZW5hbnQtb2lkY3xzYW1scHxTaWVtZW5zfFowMDJFSk5VIiwiZ2l2ZW5fbmFtZSI6IlJhcGhhZWwiLCJmYW1pbHlfbmFtZSI6IlNjaG5haXRsIiwibmlja25hbWUiOiJSYXBoYWVsIiwibmFtZSI6IlJhcGhhZWwgU2NobmFpdGwiLCJwaWN0dXJlIjoiaHR0cHM6Ly9zLmdyYXZhdGFyLmNvbS9hdmF0YXIvODkzNWVlY2QzMDc2ZTAyMTQ5ODE2MTZmZjBkZTRkZjI_cz00ODAmcj1wZyZkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZyYS5wbmciLCJ1cGRhdGVkX2F0IjoiMjAxOS0xMi0wNVQxMDo0ODozMy4wNjhaIiwiZXhwIjoxNTc1NTQzMDMzLCJpc3MiOiJodHRwczovL3NpZW1lbnMtcWEtMDAwNjkuZXUuYXV0aDAuY29tLyJ9.M39aPefXmaDGzaDd0qHcQHMhvugTVN4i4pyvGJ-7fayewU9vZdtKvSzFF9rVal8GEz7HKTr_auqMw9HemOWyag==

The key id therefore is: c818e716-5901-439d-9aed-ebdf802b6da9

Public Key:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENARdEGaEpfgHph3440UodVsQdqxi
PYz+l1aEcz+Bivr6emXDnor1nET94dbPqYxk+vtUHGkgOb44VPEZUe4ijQ==
-----END PUBLIC KEY-----

I tried to verify the code using the following approaches:

  • using the System.IdentityModel.Tokens.Jwt Namespace. But I was unable to supply the public key as string to the ValidationParameters. I followed a similar approach of this answer https://stackoverflow.com/a/51866939/2250672. It felt complicated and error prone. As I could not get it to work after a whole day, I decided to move on to one of the nuget packages that supplies the same functionality.
  • using the JWT nuget Package, but it does not support the Algorithm used by AWS ALB.
  • using Jose.JWT nuget Package using the following code:

Jose.JWT.Decode(__token, publicKeyPem, Jose.JwsAlgorithm.ES256)

getting the following error:

ERROR: Script execution failed. [ArgumentException] EcdsaUsingSha algorithm expects key to be of either CngKey or ECDsa types.

How can I simply verify the JWT from AWS ALB in C# ?

theduck
  • 2,589
  • 13
  • 17
  • 23
quadroid
  • 8,444
  • 6
  • 49
  • 82
  • Your JWT is issued by `https://siemens-qa-00069.eu.auth0.com/`. Why are you trying to validate it against AWS key? – Vlad DX Dec 09 '19 at 19:17
  • 1
    Because the JWT is generated by the aws load balancer. – quadroid Dec 09 '19 at 20:27
  • How do you explain that JWT has `https://siemens-qa-00069.eu.auth0.com/` as issuer? – Vlad DX Dec 09 '19 at 21:37
  • 2
    i want to validate the signer, which is mentioned as signer in the jwt, "signer": "arn:aws:elasticloadbalancing:eu-central-1:485683487196:loadbalancer/app/find-test-alb/57c0f1f3f84c6c21". That is why I try to validate it against the AWS key. If you try using the public key on jwt.io you will see that it says Valid. (You need to remove the trailing `=` from the signature) – quadroid Dec 10 '19 at 08:42

1 Answers1

5

The public key is not available on https://siemens-qa-00069.eu.auth0.com/.well-known/openid-configuration. So you can try a manual approach:

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

The problem is that I can't test it, because on my machine (Windows 10 + .NET Core 2.1) I get this error:

System.PlatformNotSupportedException: The specified curve 'nistP256' or its parameters are not valid for this platform. ---> Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The parameter is incorrect

Danut Radoaica
  • 1,860
  • 13
  • 17
  • Your code returns false, have you tried validating the token I provided? – quadroid Dec 16 '19 at 07:45
  • 1
    The ECDSA Creation pointed me into the correct direction, but I used the bouncy castle `PemReader` to get the X/Y Coords (they are 32 Byte long, instead of 45) Which works for me. – quadroid Dec 17 '19 at 08:38
  • The following coords work for me: 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(), } }); – quadroid Dec 17 '19 at 09:39
  • 1
    I modified the answer according to your findings. Thank you for the feedback – Danut Radoaica Dec 17 '19 at 10:27
  • On Windows 10 with .NET Core you will get a PlatformNotSupportedException if your Curve parameters are incorrect. – Ryan Williams Jun 15 '20 at 04:26