Search code examples
kotlinjwtauth0jackson-databind

Why is auth0's Java JWT library unable to accept an Object/Any for custom claims?


I am trying to create a custom JWT claim based on an object. I figured this should be doable since auth0.jwt uses jackson-databind. Here's a simple example:

                data class Foo(val strings: List<String>)

                val bar = Foo(listOf("hello", "world"))

                val jwtAlgorithm = Algorithm.RSA256(
                    loadPublicKeyFromFile("testPublicKey.pem"),
                    loadPrivateKeyFromFile("testPrivateKey_pkcs8.pem")
                )

                val payload = mapOf("customClaim" to bar)
                val token = JWT.create().withPayload(payload).sign(jwtAlgorithm)

However, I get the following exception

java.lang.IllegalArgumentException: Claim values must only be of types Map, List, Boolean, Integer, Long, Double, String and Date

I have noticed that when deserialising custom claims, I needed to add Jackson annotations (such as @JsonCreator and @JsonProperty) to my claim model classes, which I have not needed when using Jackson myself.

My project is using the following relevant libraries:

            "com.auth0:java-jwt:3.18.1",
            "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version", 
            "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version",
            "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jackson_version"

where jackson_version = 2.9.7

What is going on here, and is there a better way to fix it than writing code to convert my custom claim objects into maps?


Solution

  • I think this is because the SDK tries to validate the payload by doing things like making sure none of the values are null, which they implement by restricting the types you can use to the ones they have implemented validation for.

    This is mentioned in the readme (although it looks like they forgot to mention Map is allowed):

    Currently supported classes for custom JWT Claim creation and verification are: Boolean, Integer, Double, String, Date and Arrays of type String and Integer.

    So yes, you will need to convert to a map if you want to use the SDK. Or don't use the SDK - personally I have forked their SDK to work around its lack of support for refreshing the management API token and obeying rate-limiting. I suspect in the long run, writing your own Auth0 API client might be easier.