Uploaded image for project: 'WildFly Elytron'
  1. WildFly Elytron
  2. ELY-2111

JwkManager uses incorrect non url-safe Base64 to load the jwks endpoint

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 1.10.13.Final, 1.15.4.Final
    • 1.15.3.Final
    • None
    • None
    • Hide

      Just use the attached project. It uses the google endpoint as the jkws endpoint (https://www.googleapis.com/oauth2/v3/certs). The test should return null (not validated cos the key was not found). But it fails with a exception decoding the keys from google. The test uses last wildfly-elytron 1.15.3.Final.

      cd jkw-elytron-test
      mvn clean test
      ...
      Running com.redhat.sample.JwkManagerTest
      Mar 29, 2021 11:06:36 AM org.wildfly.security.auth.realm.token.validator.JwtValidator <init>
      WARN: ELY01126: Jwt-based token realm not configured with a list of valid issuers. Ignoring issuer verification.
      Mar 29, 2021 11:06:36 AM org.wildfly.security.auth.realm.token.validator.JwtValidator <init>
      WARN: ELY01127: Jwt-based token not configured with a list of valid audiences. Ignoring audience verification.
      Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.707 sec <<< FAILURE!
      testGoogleApiKeys(com.redhat.sample.JwkManagerTest)  Time elapsed: 0.676 sec  <<< ERROR!
      java.lang.IllegalStateException: ELY01116: Signature verification failed
      	at org.wildfly.security.auth.realm.token.validator.JwtValidator.verifySignature(JwtValidator.java:188)
      	at org.wildfly.security.auth.realm.token.validator.JwtValidator.validate(JwtValidator.java:127)
      	at com.redhat.sample.JwkManagerTest.testGoogleApiKeys(JwkManagerTest.java:95)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
      	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
      	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
      	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
      	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
      	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
      	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
      	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
      	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
      	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
      	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
      	at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
      	at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
      	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
      	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
      Caused by: java.lang.IllegalArgumentException: Illegal base64 character 5f
      	at java.util.Base64$Decoder.decode0(Base64.java:714)
      	at java.util.Base64$Decoder.decode(Base64.java:526)
      	at java.util.Base64$Decoder.decode(Base64.java:549)
      	at org.wildfly.security.auth.realm.token.validator.JwkManager.getJwksFromUrl(JwkManager.java:178)
      	at org.wildfly.security.auth.realm.token.validator.JwkManager.checkRemote(JwkManager.java:110)
      	at org.wildfly.security.auth.realm.token.validator.JwkManager.getPublicKey(JwkManager.java:75)
      	at org.wildfly.security.auth.realm.token.validator.JwtValidator.resolvePublicKey(JwtValidator.java:300)
      	at org.wildfly.security.auth.realm.token.validator.JwtValidator.createSignature(JwtValidator.java:248)
      	at org.wildfly.security.auth.realm.token.validator.JwtValidator.verifySignature(JwtValidator.java:179)
      	... 34 more
      
      Show
      Just use the attached project. It uses the google endpoint as the jkws endpoint ( https://www.googleapis.com/oauth2/v3/certs ). The test should return null (not validated cos the key was not found). But it fails with a exception decoding the keys from google. The test uses last wildfly-elytron 1.15.3.Final. cd jkw-elytron-test mvn clean test ... Running com.redhat.sample.JwkManagerTest Mar 29, 2021 11:06:36 AM org.wildfly.security.auth.realm.token.validator.JwtValidator <init> WARN: ELY01126: Jwt-based token realm not configured with a list of valid issuers. Ignoring issuer verification. Mar 29, 2021 11:06:36 AM org.wildfly.security.auth.realm.token.validator.JwtValidator <init> WARN: ELY01127: Jwt-based token not configured with a list of valid audiences. Ignoring audience verification. Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.707 sec <<< FAILURE! testGoogleApiKeys(com.redhat.sample.JwkManagerTest) Time elapsed: 0.676 sec <<< ERROR! java.lang.IllegalStateException: ELY01116: Signature verification failed at org.wildfly.security.auth.realm.token.validator.JwtValidator.verifySignature(JwtValidator.java:188) at org.wildfly.security.auth.realm.token.validator.JwtValidator.validate(JwtValidator.java:127) at com.redhat.sample.JwkManagerTest.testGoogleApiKeys(JwkManagerTest.java:95) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) Caused by: java.lang.IllegalArgumentException: Illegal base64 character 5f at java.util.Base64$Decoder.decode0(Base64.java:714) at java.util.Base64$Decoder.decode(Base64.java:526) at java.util.Base64$Decoder.decode(Base64.java:549) at org.wildfly.security.auth.realm.token.validator.JwkManager.getJwksFromUrl(JwkManager.java:178) at org.wildfly.security.auth.realm.token.validator.JwkManager.checkRemote(JwkManager.java:110) at org.wildfly.security.auth.realm.token.validator.JwkManager.getPublicKey(JwkManager.java:75) at org.wildfly.security.auth.realm.token.validator.JwtValidator.resolvePublicKey(JwtValidator.java:300) at org.wildfly.security.auth.realm.token.validator.JwtValidator.createSignature(JwtValidator.java:248) at org.wildfly.security.auth.realm.token.validator.JwtValidator.verifySignature(JwtValidator.java:179) ... 34 more
    • Undefined

      The JwkManager loads the RSA public key value "n" and "e" with the non url-safe base64 decoder.

      This is not RFC (https://tools.ietf.org/html/rfc7517) compliant. The BigInts of the RSA key are Base64URL encoded without padding. So that code should load "n" and "e" using the RFC4648 url-safe version.

      This part of the code is only used if the "jku" header is specified in the token and the implementation should retrieve the key from the endpoint to validate the token.

              rhn-support-rmartinc Ricardo Martin Camarero
              rhn-support-rmartinc Ricardo Martin Camarero
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: