Token created by Keycloak cannot be validated

Issue #134 resolved
Georg Hohenberger created an issue

Hello, when trying to port a implementation from JsonWebToken to jose4j. I discovered that the tokens generated by Keycloak (Open Id) could not be validated because of InvalidJwtSignatureException:

org.jose4j.jwt.consumer.InvalidJwtSignatureException: JWT rejected due to invalid signature. Additional details: [[9] Invalid JWS Signature: JsonWebSignature{"alg":"ES256","typ" : "JWT","kid" : "...

The reason seems to be EcdsaUsingShaAlgorithm.verifySignature in jose runs convertConcatenatedToDer() while jjwt EllipticCurveSignatureValidator.isValid has a fallback with the following comment:

If the expected size is not valid for JOSE, fall back to ASN.1 DER signature. This fallback is for backwards compatibility ONLY (to support tokens generated by previous versions of jjwt) and backwards compatibility will possibly be removed in a future version of this library.

See https://github.com/jwtk/jjwt/blob/master/impl/src/main/java/io/jsonwebtoken/impl/crypto/EllipticCurveSignatureValidator.java#L44

I have created a minimal project that reproduces the problem.

https://github.com/GeorgHohenberger/jose4j_invalid_signature_showcase

Is there anything you can do for me (in your code base)? If not can you give me some input what Keycloak does wrong, so i can report it?

Comments (7)

  1. Brian Campbell repo owner

    So, the general result of an ECDSA signature is an EC point (R, S), where R and S are unsigned (very large) integers. The output from the JCA java signature API encodes R and S into a single byte array using ASN.1 DER. The JOSE (i.e. JWS, JWE, JWA, JWK, & JWT) specs, however, mandate that R and S be encoded into a single value by concatenating them together. See https://tools.ietf.org/html/rfc7518#section-3.4 for that and https://tools.ietf.org/html/rfc7515#appendix-A.3 for a detailed example.

    It appears that Keycloak's JWS ES*** implementation is using the output from the JCA java signature API as is rather than doing the JOSE concatenating, which is resulting in an invalid JWS.

    It seems that like 3 years ago jjwt had the same defect that Keycloak has now. And when they fixed it, they left in that fallback check to allow backwards compatibility with their own library. That fallback is now why jjwt will accept the Keycloak signature as valid even though it's not per the standard.

    I made some changes to the minimal project you created to demonstrate this stuff (and prove to myself that what I just described is actually the case). Basically it takes the incorrectly formatted ECDSA signature (ASN.1 DER) off of the Keycloak JWT and converts it to the JWS/JWA standard format (concatenated R & S) and then reassembles the JWT with the correctly formatted signature. Which produces a valid and spec complaint JWT signature. https://github.com/GeorgHohenberger/jose4j_invalid_signature_showcase/pull/1

  2. Georg Hohenberger reporter

    Thank you very much for the fast answer. I will report this issue to Keycloak.

    Have a nice day

  3. Brian Campbell repo owner

    Just for posterity, please leave a comment with a link to issue you report to Keycloak.

  4. Log in to comment