0

Authentication with Auth0 is working on development but my tests are all failing with a 401 now. I have tried to mock it but get the provided error below. I feel like this is a very common problem that any tested API application would have to overcome so thought I would reach out to any Kotlin or Java devs that might know a way to solve this:

For example, this spec should pass, its Kotest with Mockk:

it("returns an empty list") {
    withService() {
        val response = client.get("/v1/users") {
            headers.append("Content-Type", "application/json")
            headers.append("Authorization", "Bearer ${token}")
        }

        response.status shouldBe HttpStatusCode.OK
        response.bodyAsText().shouldBe("""{"data":[]}""")
    }
}

Here is an example of Route setup:

fun Application.configureRouting() {
    install(Authentication) {
        jwt("auth0") {
            verifier(JwtValidator.jwkProvider, System.getProperty("AUTH_0_DOMAIN"))
            validate { credential -> JwtValidator.validateCreds(credential) }
        }
    }

    routing {
        route("/v1") {
            userRouting()
        }
    }
}

fun Route.userRouting() {
    authenticate("auth0") {
        route("/users") {
            get {
                val users = transaction { User.all().map { it.to_json() } }
                call.respond(mapOf("data" to users))
            }
        }
    }
}

I have tried to mock it but it's turned into mock city.

            it("returns an empty list") {
                setTestEnvVariables()

                val jwkProvider = mockk<JwkProvider>()
                val jwk = mockk<Jwk>()
                val publicKey: RSAPublicKey = generateTestKeyPair().public as RSAPublicKey

                // Create a non-relaxed mock for the JWTVerifier
                val verifier = mockk<JWTVerifier>()

                val decodedJwt = mockk<DecodedJWT>()

                mockkObject(JwtValidator) // Mock the JwtValidator object

                // Mock the behavior of JwtValidator.jwkProvider
                every { JwtValidator.jwkProvider } returns jwkProvider

                // Mock the behavior of JwtValidator.validateCreds
                every { JwtValidator.validateCreds(any()) } returns JWTPrincipal(mockk())

                // Mock the behavior of JwkProvider.get
                every { jwkProvider.get(any()) } returns jwk

                // Mock the behavior of Jwk.getAlgorithm
                every { jwk.getAlgorithm() } returns "RS256"

                // Mock the behavior of Jwk.getPublicKey
                every { jwk.publicKey } returns publicKey

                // Return the mocked DecodedJWT on successful verification
                every { verifier.verify(authorizationToken) } returns decodedJwt

                withService() {
                    val response = client.get("/v1/users") {
                        headers.append("Content-Type", "application/json")
                        headers.append("Authorization", "Bearer ${token}")
                    }

                    response.status shouldBe HttpStatusCode.OK
                    response.bodyAsText().shouldBe("""{"data":[]}""")
                }
            }

Here is the error it gets with a mocked test

2023-07-20 08:47:17.407 [DefaultDispatcher-worker-1] TRACE io.ktor.auth.jwt - Token verification failed
com.auth0.jwt.exceptions.SignatureVerificationException: The Token's Signature resulted invalid when verified using the Algorithm: SHA256withRSA
  at com.auth0.jwt.algorithms.RSAAlgorithm.verify(RSAAlgorithm.java:51)
  at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:463)
  at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:445)
2023-07-20 08:47:17.408 [DefaultDispatcher-worker-1] TRACE io.ktor.se
joeyk16
  • 1,357
  • 22
  • 49
  • Basically, you need to mock only the JwkProvider. Here (https://github.com/ktorio/ktor-samples/blob/main/jwt-auth-tests/src/test/kotlin/io/ktor/samples/jwtauth/ApplicationTest.kt) you can find an example of the test. – Aleksei Tirman Jul 20 '23 at 06:57

0 Answers0