Skip to content

Conversation

@artem-v
Copy link
Contributor

@artem-v artem-v commented Oct 28, 2025

Fixes #117

Main changes

  • Get rid of jjwt, use auth0-java-jwt instead.
  • Renamings:
    • renamed artifact: scalecube-security-tokens -> scalecube-security-jwt.
    • renamed package: io.scalecube.security.tokens.jwt -> io.scalecube.security.jwt.
    • renamed few classes/methods: JsonwebtokenResolver -> JwksTokenResolver, JwksKeyLocator -> JwksKeyProvider.
  • Added more javadocs.

What didn't change

  • It's a same semantic as before: interface JwtTokenResolver, + JWKS based implementation JwksTokenResolver, + JwksKeyProvider that retrieves and caches RSA keys from remote endpoint.
  • Same limitation as before: it only works for alg RSA.

@artem-v artem-v changed the title Get rid of jjwt, use auth0.java-jwt instead Get rid of jjwt, use auth0-java-jwt instead Oct 28, 2025
@artem-v artem-v marked this pull request as draft October 28, 2025 10:11
@aharonha
Copy link
Contributor

Not the first time I see codebase that want to stop using jjwt

@artem-v artem-v marked this pull request as ready for review October 31, 2025 07:23
@artem-v artem-v merged commit d0d8b63 into master Oct 31, 2025
1 check passed
@artem-v artem-v deleted the try-auth0-jwt branch October 31, 2025 07:43
@artem-v
Copy link
Contributor Author

artem-v commented Oct 31, 2025

@dmytro-lazebnyi
As you correctly pointed out that in 0.12.7 they must have been fixed potentially class-loader issues. So i have tried latest jjwt (0.13.0), applied it on our service (scalecube-security branch is try-latest-jjwt):

$ mvn dependency:tree | grep security
[INFO] |  +- io.scalecube:scalecube-services-security:jar:2.13.9.jjwt.rc1:compile
[INFO] |  +- io.scalecube:scalecube-security-jwt:jar:1.1.8.jjwt.rc1:compile
[INFO] |  +- io.scalecube:scalecube-security-vault:jar:1.1.8.jjwt.rc1:compile
[INFO] |  +- io.scalecube:scalecube-services-security:jar:2.13.9.jjwt.rc1:compile
[INFO] |  +- io.scalecube:scalecube-security-jwt:jar:1.1.8.jjwt.rc1:compile
[INFO] |  +- io.scalecube:scalecube-security-vault:jar:1.1.8.jjwt.rc1:compile

Then in ITs there's this:

Caused by: io.scalecube.security.jwt.JwtTokenException: Failed to resolve JWT: ey***3A
  at io.scalecube.security.jwt.JwksTokenResolver.lambda$resolveToken$1(JwksTokenResolver.java:66) ~[service-develop-SNAPSHOT.jar:?]
  at java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) ~[?:?]
  at java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) ~[?:?]
  at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1773) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:387) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java) ~[?:?]
  at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312) ~[?:?]
  at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843) ~[?:?]
  at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808) ~[?:?]
  at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188) ~[?:?]
Caused by: java.util.concurrent.CompletionException: java.lang.NoClassDefFoundError: Could not initialize class io.jsonwebtoken.Jwts
  at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) ~[?:?]
  at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1770) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:387) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java) ~[?:?]
  at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312) ~[?:?]
  at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843) ~[?:?]
  at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808) ~[?:?]
  at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188) ~[?:?]
Caused by: java.lang.NoClassDefFoundError: Could not initialize class io.jsonwebtoken.Jwts
  at io.scalecube.security.jwt.JwksTokenResolver.lambda$resolveToken$0(JwksTokenResolver.java:32) ~[service-develop-SNAPSHOT.jar:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1768) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:387) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java) ~[?:?]
  at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312) ~[?:?]
  at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843) ~[?:?]
  at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808) ~[?:?]
  at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188) ~[?:?]
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ClassCastException: class io.jsonwebtoken.impl.DefaultJwtBuilder$Supplier cannot be cast to class io.jsonwebtoken.lang.Supplier (io.jsonwebtoken.impl.DefaultJwtBuilder$Supplier is in unnamed module of loader 'app'; io.jsonwebtoken.lang.Supplier is in unnamed module of loader java.net.URLClassLoader @2343e037) [in thread "ForkJoinPool.commonPool-worker-6"]
  at io.jsonwebtoken.Jwts.<clinit>(Jwts.java:1006) ~[service-develop-SNAPSHOT.jar:?]
  at io.scalecube.security.jwt.JwksTokenResolver.lambda$resolveToken$0(JwksTokenResolver.java:32) ~[service-develop-SNAPSHOT.jar:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1768) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) ~[?:?]
  at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:387) ~[?:?]
  at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java) ~[?:?]
  at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312) ~[?:?]

This is exception from ITs during m2m auth. Exception now is little bit different, but it is still CCE as before. I.e. they refactored code to suppliers, but it still didn't solve a problem:

Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ClassCastException: class io.jsonwebtoken.impl.DefaultJwtBuilder$Supplier cannot be cast to class io.jsonwebtoken.lang.Supplier (io.jsonwebtoken.impl.DefaultJwtBuilder$Supplier is in unnamed module of loader 'app'; io.jsonwebtoken.lang.Supplier is in unnamed module of loader java.net.URLClassLoader @2343e037)

I.e. we have io.jsonwebtoken.impl.DefaultJwtBuilder$Supplier from application classloader (a classpath one), and io.jsonwebtoken.lang.Supplier from java.net.URLClassLoader from the app that is running in its own isolated classloader.

A code in the io.jsonwebtoken.lang.Classes#forName still not changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Find classloader-safe solution for jwt tokens

4 participants