auth0 / java-jwt

Java implementation of JSON Web Token (JWT)
MIT License
5.89k stars 922 forks source link

what about a xml format rs256 #220

Closed samuelweiwei closed 6 years ago

samuelweiwei commented 6 years ago

I hava a public token and a component like

<Exponent>AQAB</Exponent>

public key example:

pYCFWhB51AUVcjpIRtoGX6-2fhZa27jeYbtcauujz6-feV9uk7P1gnDVRJsAaHoj1RuE6EG81QnFKkDXq-HZU5xLFczpZRfj3y3aIaBmdidHDVE5WSVpgOZho03p5ns7dDr2rPso552_25NDaf3pNqqoGx4XMj066oxwKnm8ivX_yLa0yaY9qstCUuROEOJ7AY3Jf_XlMXv7clKFGmTiPYVz5xcBj8QgC5hI0gxWjjIx8Ns9aHjKzZ5MrN3iHoUfXBQY5glaeA3Nb71EgRLlP5kPJsYLwNN50r4ZzXb9HAJ8iB4aeOOQZfJWTgL__vRdL1Wc7De-g75ENQwxOlfQRw

Golang decode this jwt use two parameters, first is public key ,second is exponent , then get correct. verified. Does auth0 support it?I use following code get a "too much data" wrong:

String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjdmNjRmNDUzODg1M2I5Yzg5MDlkZWRiNmVhMTNkN2U5NmMwNjRmNTgifQ.eyJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjU1NTYvZGV4Iiwic3ViIjoiQ2hJek1EQXhNVEV3TURBeE5UWTNNekEyT1RRIiwiYXVkIjoibG9naW5fc2VydmVyIiwiZXhwIjoxNTEwNzEyNjkxLCJpYXQiOjE1MTA2MjYyOTEsIm5vbmNlIjoibi0wUzZfV3pBMk1qIiwiYXRfaGFzaCI6IlUwNkplUktTWk5rTmpMQUcwdy1DOVEiLCJlbWFpbCI6InpoYW5neXVuamlhbkB3YW5kYS5jbiIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpZGVudGl0eV92ZXJpZmllZCI6dHJ1ZSwiQWNjb3VudCI6IiIsInVzZXJuYW1lIjoiMTU5MDE4NjMzNzAiLCJ1c2VyaWQiOiIzMDAxMTEwMDAxNTY3MzA2OTQifQ.Ko8cXz_hBRLmy7DD-_bE0vTvVzsjETXf__LfvT8q9tXuVP0TAFdFJxN_Rqy9_zEyRn2oFYtG_TozmbnFw3sWeti8YVZ5kO0CHxWeXbPUlpEioi-Svzczyn8vcSqXH62gifzIDmvsnt5NepoLpAtCy-dHKr_WpD1CSClBg62lE-q0u6p6EhZsiP2Xo7Eik0mwulyPqbFJVrjnirjboUdkShuuQv7pampkTEVnUom1FFar5OExSDj4ODMDQXHieGiOwFf2ZPmNM5tITf3Q_HNvG1Q8NKQIiYjyiUnH_UtLEEbndgpVvr6z9RVEZi81AayvJoZXCoE95LUP7WfMUgQBzQ";

String publickeystr = "pYCFWhB51AUVcjpIRtoGX6-2fhZa27jeYbtcauujz6-feV9uk7P1gnDVRJsAaHoj1RuE6EG81QnFKkDXq-HZU5xLFczpZRfj3y3aIaBmdidHDVE5WSVpgOZho03p5ns7dDr2rPso552_25NDaf3pNqqoGx4XMj066oxwKnm8ivX_yLa0yaY9qstCUuROEOJ7AY3Jf_XlMXv7clKFGmTiPYVz5xcBj8QgC5hI0gxWjjIx8Ns9aHjKzZ5MrN3iHoUfXBQY5glaeA3Nb71EgRLlP5kPJsYLwNN50r4ZzXb9HAJ8iB4aeOOQZfJWTgL__vRdL1Wc7De-g75ENQwxOlfQRw";

        Decoder decoder = Base64.getUrlDecoder();
        byte[] byteKey = decoder.decode(publickeystr);
        X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
        KeyFactory kf;
        try {
            kf = KeyFactory.getInstance("RSA");
            PublicKey publicKey = kf.generatePublic(X509publicKey);
            RSAPrivateKey privateKey = null;
            Algorithm algo = Algorithm.RSA256(((RSAPublicKey)publicKey), privateKey);
            JWTVerifier verifier = JWT.require(algo).withIssuer("http://127.0.0.1:5556/dex").build();
            DecodedJWT jwt = verifier.verify(token);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

How is the settlement.

lbalmaceda commented 6 years ago

I don't understand your question 🤔 . If you need guidance on how to load a public key you could try with the methods used in our tests, which are not included in the library but you can see here. Again, this library does NOT parse or create the keys for you, that's out of the scope.

The JWT configuration code you've shared looks OK, but the one where you read the key contents doesn't. Normally you would download the public key in a .pem format and put it in your project's resources, or use a library like https://github.com/auth0/jwks-rsa-java to recreate the public key from a JWKs file like https://lbalmaceda.auth0.com/.well-known/jwks.json URL (replace lbalmaceda with your auth0's account name).

samuelweiwei commented 6 years ago

The RSA key is in several ways: 1) Binary DER-encoded format. This is sometimes called ASN.1 BER-encoded (there is a subtle difference between BER- and DER-encodings: DER is just a stricter subset of BER). The most compact form. If you try to view the file with a text editor it is full of "funny" characters. The first character in the file is almost always a '0' character (0x30). 2) PEM or base64 format. This is the same data as the DER-encoded file but it is encoded in base64 with additional header and footer lines: -----BEGIN FOO BAR KEY----- MIIBgjAcBgoqhkiG9w0BDAEDMA4ECKZesfWLQOiDAgID6ASCAWBu7izm8N4V 2puRO/Mdt+Y8ceywxiC0cE57nrbmvaTSvBwTg9b/xyd8YC6QK7lrhC9Njgp/ ... -----END FOO BAR KEY----- These files can be viewed with a text editor and can be easily transmitted as part of an email message. 3) XML format. There are W3C standards for this, and, er, a .NET way that predates the latest W3C standard.

Above code just settle the pem or base64 format, but with xml format, there is N(modulus), E(exponent) two factors must be set into the RSAPublicKeySpec. java.security.spec.RSAPublicKeySpec.RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent) how to use java-jwt in this format to verify a token

samuelweiwei commented 6 years ago

I change the code to below which will leads to a verify fail but not too much data exception. I think it's a right way to decode but still some misusing.

String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjdmNjRmNDUzODg1M2I5Yzg5MDlkZWRiNmVhMTNkN2U5NmMwNjRmNTgifQ.eyJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjU1NTYvZGV4Iiwic3ViIjoiQ2hJek1EQXhNVEV3TURBeE5UWTNNekEyT1RRIiwiYXVkIjoibG9naW5fc2VydmVyIiwiZXhwIjoxNTEwNzEyNjkxLCJpYXQiOjE1MTA2MjYyOTEsIm5vbmNlIjoibi0wUzZfV3pBMk1qIiwiYXRfaGFzaCI6IlUwNkplUktTWk5rTmpMQUcwdy1DOVEiLCJlbWFpbCI6InpoYW5neXVuamlhbkB3YW5kYS5jbiIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpZGVudGl0eV92ZXJpZmllZCI6dHJ1ZSwiQWNjb3VudCI6IiIsInVzZXJuYW1lIjoiMTU5MDE4NjMzNzAiLCJ1c2VyaWQiOiIzMDAxMTEwMDAxNTY3MzA2OTQifQ.Ko8cXz_hBRLmy7DD-_bE0vTvVzsjETXf__LfvT8q9tXuVP0TAFdFJxN_Rqy9_zEyRn2oFYtG_TozmbnFw3sWeti8YVZ5kO0CHxWeXbPUlpEioi-Svzczyn8vcSqXH62gifzIDmvsnt5NepoLpAtCy-dHKr_WpD1CSClBg62lE-q0u6p6EhZsiP2Xo7Eik0mwulyPqbFJVrjnirjboUdkShuuQv7pampkTEVnUom1FFar5OExSDj4ODMDQXHieGiOwFf2ZPmNM5tITf3Q_HNvG1Q8NKQIiYjyiUnH_UtLEEbndgpVvr6z9RVEZi81AayvJoZXCoE95LUP7WfMUgQBzQ";

String publickeystr = "pYCFWhB51AUVcjpIRtoGX6-2fhZa27jeYbtcauujz6-feV9uk7P1gnDVRJsAaHoj1RuE6EG81QnFKkDXq-HZU5xLFczpZRfj3y3aIaBmdidHDVE5WSVpgOZho03p5ns7dDr2rPso552_25NDaf3pNqqoGx4XMj066oxwKnm8ivX_yLa0yaY9qstCUuROEOJ7AY3Jf_XlMXv7clKFGmTiPYVz5xcBj8QgC5hI0gxWjjIx8Ns9aHjKzZ5MrN3iHoUfXBQY5glaeA3Nb71EgRLlP5kPJsYLwNN50r4ZzXb9HAJ8iB4aeOOQZfJWTgL__vRdL1Wc7De-g75ENQwxOlfQRw";

Decoder decoder = Base64.getUrlDecoder(); byte[] byteKey = decoder.decode(publickeystr); byte[] x = "AQAB".getBytes(); BigInteger byteKeyInt = new BigInteger(byteKey); BigInteger byteX = new BigInteger(x); RSAPublicKeySpec pub = new RSAPublicKeySpec(byteKeyInt, byteX); KeyFactory kf; try { kf = KeyFactory.getInstance("RSA"); PublicKey publicKey = kf.generatePublic(pub); RSAPrivateKey privateKey = null; Algorithm algo = Algorithm.RSA256(((RSAPublicKey)publicKey), privateKey); JWTVerifier verifier = JWT.require(algo).build(); DecodedJWT jwt = verifier.verify(token); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchAlgorithmException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (InvalidKeySpecException e) { // TODO Auto-generated catch block e.printStackTrace(); }