Integrate Auth0 with Ktor single-page app

Hi, all. I’m developing a Ktor single-page web app and I intend to integrate Auth0 with it but I haven’t found enough documentation for Auth0 with Kotlin so far. I’m following the steps described on Adding Auth0 Authorization to a Ktor HTTP API, but I’m struggling to connect our web app to my Auth0 API and App. I really hope I could get some help from you.

Below is an extract of the main parts of the code. I’m getting “HTTP ERROR 401” when trying http://localhost:8080/api/messages/protected.

fun Route.homepage() {

get("/api/messages/public") {
    call.respondText(
        """{"message": "The API doesn't require an access token to share this message."}""",
        contentType = ContentType.Application.Json
    )
}

authenticate("auth0") {

    get("/api/messages/protected") {
        call.respondText(
            """{"message": "The API successfully validated your access token."}""",
            contentType = ContentType.Application.Json
        )
    }
}

}

fun validateCreds(credential: JWTCredential): JWTPrincipal? {

val containsAudience = credential.payload.audience.contains(System.getenv("AUDIENCE"))

if (containsAudience) {
    return JWTPrincipal(credential.payload)
}

return null

}

fun Application.module() {

install(ContentNegotiation) {
    json()
}

install(CORS) {
    method(HttpMethod.Get)
    method(HttpMethod.Post)
    method(HttpMethod.Delete)
    header(HttpHeaders.ContentType)  

    //anyHost()
    method(HttpMethod.Options)
    method(HttpMethod.Get)
    header("authorization")
    allowCredentials = true
    allowNonSimpleContentTypes = true

}

val jwkProvider = JwkProviderBuilder(System.getenv("ISSUER"))
    .cached(10, 24, TimeUnit.HOURS)
    .rateLimited(10, 1, TimeUnit.MINUTES)
    .build()

install(Authentication) {
    jwt("auth0") {
        verifier(jwkProvider, System.getenv("ISSUER"))
        validate { credential -> validateCreds(credential) }
    }
}

install(Compression) {
    gzip()
}

routing {
    homepage()
}

}

I’ve set ISSUER and AUDIENCE as environment variables

Hey there @jperfit welcome to the community!

I admittedly don’t have a ton of experience with Ktor (think it’s awesome :smile:) but I have been able to successfully validate an access token from a React SPA with a Ktor API, similar to the blog post you referenced. Nothing really stands out in the code you’ve shared.

Given you’re receiving a 401, I’d expect to see a reason why in the logging where you have your API running. Are you able to confirm?

Do you have a trailing slash on your Auth0 issuer’s value?

1 Like

Hi @mraible. I didn’t have a trailing slash, I add it and nothing changed :confused:

Hi @tyf. Thanks for the replay. Do you mean in my Auth0 Dashboard?

Hey @jperfit! No problem, happy to help where I can :slight_smile:

I’m referring to logging from the API itself - I used the KTor sample API from the guide you linked and was receiving a 401 as well at first, but when I looked at the logging from the API (I just ran it in VS Code) it was complaining about the iss value like:

io.ktor.auth.jwt - Token verification failed: The Claim 'iss' value doesn't match the required issuer.

Once I made sure the issuer I defined in my SPA code to authorize/receive tokens was exactly the same as the issuer defined in the KTor API I was able to validate successfully.