jwt-dotnet / jwt

Jwt.Net, a JWT (JSON Web Token) implementation for .NET
Other
2.14k stars 462 forks source link

Help enabling support for RSA256?! #173

Closed khesualdo closed 6 years ago

khesualdo commented 6 years ago

@sparachi @abatishchev @djavier

Based on the current version of the library how can I modify the following code to support RSA256? This is sample code from readme.

            try
            {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);

                var json = decoder.Decode(token, secret, verify: true);
                Debug.WriteLine(json);
            }
            catch (TokenExpiredException)
            {
                Debug.WriteLine("Token has expired");
            }
            catch (SignatureVerificationException)
            {
                Debug.WriteLine("Token has invalid signature");
            }

I get the following error when using the above code For algorithm RS256 please create custom factory by implementing IAlgorithmFactory

abatishchev commented 6 years ago

See https://github.com/jwt-dotnet/jwt/blob/master/src/JWT/Algorithms/RS256Algorithm.cs

khesualdo commented 6 years ago

What should I be looking at in that file?

khesualdo commented 6 years ago

@abatishchev I was hoping for some example code, since I am very new to this.

Based on the code the @sparachi wrote, pubKey should be the JWKs? Or should it be a specific key, based on the kid tag from the header?

byte[] pubKey = GetPublicKeyFromCache();
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
var algorithmFactory = new RSAlgorithmFactory(CertFactory);
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithmFactory);
var accessTokenData = decoder.DecodeToObject<JwsTokenData>(accessToken, pubKey, true);

private X509Certificate2 CertFactory()
{
        byte[] pubKey = GetPublicKeyFromCache();
        var cert = new X509Certificate2(pubKey);
        return cert;
}
abatishchev commented 6 years ago

I'm not familiar with JWK. It should be a byte array corresponding to a cert with both public and private keys.

khesualdo commented 6 years ago

So then pubKey would be a value from any x5* tags? Also did you guys figure out why @sparachi 's code was giving him errors?

abatishchev commented 6 years ago

What is x5 tags? I'm not familiar, sorry.

khesualdo commented 6 years ago

Well, I need to verify an AzureAD JWT for openIdConnect, the following is the header of the token

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "7_Zuf1tvkwLxYaHS3q6lUjUYIGw",
  "kid": "7_Zuf1tvkwLxYaHS3q6lUjUYIGw"
}

I have never actually used x5 tags so I am not familiar, but when I verified the jwt manually I would use the kid tag to look up a specific key in the jwks set.

Did you guys figure out why @sparachi 's code was giving him errors? I honestly need a working code, reading other issues seems like the code is there, but I need to enable something manually, but I am not familiar with the code. What do I need to enable to make the library work with the RSA256 algorithm?

abatishchev commented 6 years ago

Will this doc in regards to x5t?

hardeepsingh21 commented 5 years ago

I am getting the same error...Does any one has working code?

abatishchev commented 5 years ago

Are you using RSAlgorithmFactory already?

megasuperlexa commented 5 years ago

So how do I decode RSA256 encoded JWT? RSAlgorithmFactory requires certificate, I only have public key (which should be sufficient to decode?).

abatishchev commented 5 years ago

You'll be able to decide but won't be able to verify the signature. You can pass whatever you have to the algorithm directly, see RS256Algorithm#L30.

But why you have only the public key?

megasuperlexa commented 5 years ago

But why you have only the public key?

I think this is quite common - to have public key to be able to verify asymmetric key signature? I dont need to sign jwt myself.

abatishchev commented 5 years ago

Hmm, actually you're right, please disregard my previous comment. With private key you can sign data and work public key you can verify it. See the other two methods on the algorithm.

The only issue right now that the methods and constrictors on the factory don't match those on the algorithm.

Please confirm that instantiating the algorithm directly and passing it to jwt encoder/decoder worked for you?