NoMethodError when calling JJWT from Kotlin - spring-boot

I'm working on a small Spring Boot application in Kotlin and now I want to secure it using JJWT. Roughly speaking, I am translating this tutorial to my use case: https://jakublesko.com/spring-security-with-jwt/
In the project I have this AuthenticationFilter:
class JwtAuthenticationFilter(val authManager: AuthenticationManager) : UsernamePasswordAuthenticationFilter() {
// other stuff omitted for brevity
override fun successfulAuthentication(request: HttpServletRequest?, response: HttpServletResponse?, chain: FilterChain?, authResult: Authentication?) {
val user = authResult?.principal as User
val roles = user.authorities
.stream()
.map(GrantedAuthority::getAuthority)
val signingKey = JWT_SECRET.toByteArray()
val token = Jwts.builder()
.signWith(SignatureAlgorithm.HS512, Keys.hmacShaKeyFor(signingKey))
.setHeaderParam("typ", TOKEN_TYPE) // validate that "typ" does not actually mean "type"
.setIssuer(TOKEN_ISSUER)
.setAudience(TOKEN_AUDIENCE)
.setSubject(user.username)
.setExpiration(Date(System.currentTimeMillis() + 864000000))
.claim("rol", roles)
.compact()
response?.addHeader(TOKEN_HEADER, TOKEN_PREFIX + token)
}
}
When I post to the authentication URL that is supposed to issue a token though, I receive:
java.lang.NoSuchMethodError: io.jsonwebtoken.SignatureAlgorithm.getMinKeyLength()I
at io.jsonwebtoken.security.Keys.hmacShaKeyFor(Keys.java:69) ~[jjwt-api-0.10.7.jar:na]
I can debug into the successfulAuthentication method and see that it is called with reasonable parameters. What catches my eye is the "I" after the parenthesis at the end of the getMinKeyLength()I. My googling skills apparently do not suffice to find a reason why it is there, but I strongly suspect it is related to reflection & calling Java libs from Kotlin code.
Is anyone around who can tell me how to fix this? I have run out of guesses.

I stumbled upon the same issue. The reason for this is most probably a dependency conflict. Check if you have any other dependency using jjwt. For us it was com.twilio.sdk.
You can do it using
mvn dependency:tree -Dverbose
After you've identified the conflicting dependency you can either match your jjwt version or exclude it from the dependency.

to run java code from Kotlin, please put the java sources under the folder
main/java
Also, your kotlin sources are located under main/kotlin

Related

Creating RepositorySystemSession using Aether

I'm trying to get all transitive dependencies of a maven project in a List of Artifacts.
I found the documentation of Aether with some example code to set up the process. One part of it is the RepositorySystem.
private static RepositorySystem newRepositorySystem() {
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
locator.addService(TransporterFactory.class, FileTransporterFactory.class);
locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
return locator.getService(RepositorySystem.class);
}
But I get a NullPointerException in the return value.
I have no idea why?
Big thanks

Problem with Protostream and UUID in Infinispan 13.0.0.Final

I'm using Infinispan 13.0.0.final with the default marshaller (protobuf). When I try to use UUID fields in my datatypes
data class CounterState(
#get:ProtoField(number = 1) var index: Long? = null,
#get:ProtoField(number = 2) var uuid: UUID? = null
)
I get the following error at build time:
.../gradle-kotlin-protobuf/build/tmp/kapt3/stubs/main/io/radiosphere/ProtoSchema.java:8: error: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: The class java.util.UUID must be instantiable using an accessible no-argument constructor.
public abstract interface ProtoSchema extends org.infinispan.protostream.GeneratedSchema {
It seems like I'm not allowed to use UUID in my types unless I generate a protoschema for it, but since UUID is a class outside of my control I can't do this.
Previous questions on the topic have gotten the suggestion to use the JavaSerializationMarshaller, but I want to solve this while still using the Protostream Marshaller. It has also been suggested that this would be fixed in version 12.0.0 here.
An example of this not working can be found here. Note that this project will not build because of the annotation processing failing as mentioned above. If it would build the proof that it is working would be shown by running the main project (ie. not the tests).
The question becomes: What do I need to do to configure UUID to be usable in my protobuf marshalled classes in Infinispan 13? Both for embedded and for a program using the hotrod client?
EDIT:
Based on a given answer I have also tried doing the following:
#AutoProtoSchemaBuilder(
includeClasses = [UUIDAdapter::class, CounterState::class],
schemaPackageName = "tutorial")
interface ProtoSchema : GeneratedSchema {
}
This makes the build work, but when starting Quarkus I get the following error:
Caused by: org.infinispan.protostream.DescriptorParserException: Duplicate type id 1005 for type org.infinispan.protostream.commons.UUID. Already used by tutorial.UUID
at org.infinispan.protostream.descriptors.ResolutionContext.checkUniqueTypeId(ResolutionContext.java:151)
at org.infinispan.protostream.descriptors.ResolutionContext.addGenericDescriptor(ResolutionContext.java:97)
at org.infinispan.protostream.descriptors.FileDescriptor.collectDescriptors(FileDescriptor.java:313)
at org.infinispan.protostream.descriptors.FileDescriptor.resolveDependencies(FileDescriptor.java:245)
at org.infinispan.protostream.descriptors.FileDescriptor.resolveDependencies(FileDescriptor.java:210)
at org.infinispan.protostream.descriptors.ResolutionContext.resolve(ResolutionContext.java:57)
at org.infinispan.protostream.impl.SerializationContextImpl.registerProtoFiles(SerializationContextImpl.java:127)
at org.infinispan.protostream.types.java.CommonTypesSchema.registerSchema(CommonTypesSchema.java:49)
at org.infinispan.client.hotrod.RemoteCacheManager.registerSerializationContextInitializer(RemoteCacheManager.java:422)
at org.infinispan.client.hotrod.RemoteCacheManager.registerDefaultSchemas(RemoteCacheManager.java:437)
at org.infinispan.client.hotrod.RemoteCacheManager.initializeProtoStreamMarshaller(RemoteCacheManager.java:409)
at org.infinispan.client.hotrod.RemoteCacheManager.actualStart(RemoteCacheManager.java:365)
at org.infinispan.client.hotrod.RemoteCacheManager.start(RemoteCacheManager.java:334)
at org.infinispan.client.hotrod.RemoteCacheManager.<init>(RemoteCacheManager.java:192)
at org.infinispan.client.hotrod.RemoteCacheManager.<init>(RemoteCacheManager.java:149)
at io.quarkus.infinispan.client.runtime.InfinispanClientProducer.initialize(InfinispanClientProducer.java:68)
If I instead change to use dependsOn like this:
#AutoProtoSchemaBuilder(
includeClasses = [CounterState::class],
dependsOn = [org.infinispan.protostream.types.java.CommonTypes::class, org.infinispan.protostream.types.java.CommonContainerTypes::class],
schemaPackageName = "tutorial")
I'm back to the build failing with:
error: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: The class java.util.UUID must be instantiable using an accessible no-argument constructor.
public abstract interface ProtoSchema extends org.infinispan.protostream.GeneratedSchema {
It seems to be like Quarkus and the Annotation processor are getting in each others way here when it comes to having a simple working solution for UUID marshalling.
You have to include the org.infinispan.protostream.types.java.util.UUIDAdapter class in your annotation:
#AutoProtoSchemaBuilder(includeClasses = [CounterState::class, UUIDAdapter::class] , schemaPackageName = "tutorial")
For more info, check the documentation page.

Jenkins gives access restriction for javax/smartcardio

For a Java / OSGi project I need to communicate with a smartcard plugged to my computer. I do this using the package javax.smartcardio.
When I first imported this package and wanted to use it, Eclipse anounced an error "Access restriction: The type 'CommandAPDU' is not API". As proposed on https://www.javacardos.com/javacardforum/viewtopic.php?t=918, I added an Accessibility Rule Pattern to the Build Path. After that, everything worked fine and I could use the package in my local environment.
But now I wanted to pass the project to our continous integration system, which is Jenkins with Maven. I also committed the .classpath file. And there I get the same error:
[ERROR] import javax.smartcardio.CommandAPDU;
[ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[ERROR] Access restriction: The type 'CommandAPDU' is not API (restriction on classpath entry '/disc2/lunifera/server/jenkins/workspace/tools/hudson.model.JDK/JDK-8/jre/lib/rt.jar')
For some reason, the access rule does not seem to work on Jenkins. Does anybody know how to solve this problem? Thanks alot.
Not exactly the kind of answer I hoped for, but in the end, I overcame the problem by using reflection. I wrote wrapper classes for the classes from javax.smartcardio that I needed. These wrapper classes hold instances of the original classes and operate on them purely by reflection. For example, the CardTerminal class wrapper may look like this:
public class CardTerminal {
private Object originalCardTerminal;
public CardTerminal(Object originalCardTerminal)
{
this.originalCardTerminal = originalCardTerminal;
}
public Card connect(String protocol)
{
try
{
Class originalCardTerminalClass = Class.forName("javax.smartcardio.CardTerminal");
Method connectMethod = originalCardTerminalClass.getMethod("connect", String.class);
Object originalCard = connectMethod.invoke(originalCardTerminal, protocol);
if (originalCard == null)
{
return null;
}
else
{
return new Card(originalCard); // "Card" is another wrapper type, of course
}
}
catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
return null;
}
}}
Of course, this is not a good solution because all the objects are just of type "object" and you lose type safety. But it's the best solution I found so far, and it's working, because you don't need to import anything from javax.smartcardio.

How can I fix Unresolved reference: Gson?

I'm trying to follow a tutorial about Android application. I'm using an dependency Fuel (which has a dependency to com.google.Gson deserializer). But Gson() is not imported by IDE.
I've tried to specify lower version of gson. I've re-synchronized all project gradle. I've tried to write import manually (import com.google.gson.Gson), but I can't use Gson() constructor. I've read manual about using Gson, but nothing seem to be changed. It's always the same way. Call constructor Gson() and after all static method... Gson().fromJson(....)
Here is section in my build.gradle (module:app)
// Fuel HTTP Client
implementation 'com.github.kittinunf.fuel:fuel:2.2.0'
implementation 'com.github.kittinunf.fuel:fuel-android:2.2.0'
implementation 'com.github.kittinunf.fuel:fuel-gson:2.2.0'
and In code, I'm using in ArticleDataProvider.kt:
class WikipediaDataDeserializer : ResponseDeserializable<WikiResults> {
override fun deserialize(reader: Reader): WikiResults? {
return Gson().fromJson(reader, WikiResults::class.java)
}
}
Normally, I would to have Gson() recognised by IDE and I wound be able to call .fromJson() normally. Gradle was downloaded properly. (I don't have any message error about).
Using this Lib in your gradle:
dependencies{
implementation 'com.google.code.gson:gson:2.8.2'
}
The problem is probably in dependency of fuel-gson:2.2.0
To bypass it, I added a new dependency to my build.gradle manually and problem is solved.
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}
Its may happen due to different versions of gson in External Libraries. To resolve it I have added following resolveStrategy in app module build.gradle.
configurations.all {
resolutionStrategy.preferProjectModules()
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.google.code.gson') {
details.useVersion "2.8.5"
}
}
}

Override spring boot dependency version with gradle kotlin-dsl

SpringBoot comes with a lot of dependencies plus default versions for them.
In groovy-gradle, such dependency versions can be overridden with:
ext['mockito.version'] = '1.7.5'
But this doesn't work for the kotlin-dsl.
I tried:
val mockito by extra { "2.12.0" }
val mockito.version by extra { "2.12.0" }
val `mockito.version` by extra { "2.12.0" }
The latter two, don't compile, the first one, isn't doing the job.
How can the version be overridden within the kotlin file (I don't want to create a separate properties file if it is somehow possible).
Try extra["mockito.version"] = "1.7.5"

Resources