https://kotlinlang.org logo
Title
e

Eman

04/27/2023, 10:34 AM
Hello everyone, i am new to ktor and would like to get help about this code:
post("api/auth/endpoint") {

// start - block of code that is repeated
  val principal = call.principal<JWTPrincipal>()
        val userId = principal?.getClaim("userId", String::class)
        if (userId == null) {
            call.respond(
                HttpStatusCode.Forbidden,
                CyrCloError(401, "User not authenticated. Please login in again")
            )
            return@post
        }
// end
}


how can this code refactored? because i have been keep repeating that code to my other endpoints
Thanks,
e

edrd

04/27/2023, 1:24 PM
There are several options, but I think the best one is to use the Authentication plugin: https://ktor.io/docs/authentication.html#authenticate-route
e

Eman

04/27/2023, 1:44 PM
yes thanks, i am using jwt authentication,
but i want to refactor the block that gets the userId, so that method i can re-use in other routes
e

edrd

04/27/2023, 2:07 PM
Oh, sorry
You could create an extension function that receives the user, like:
@JvmInline
value class UserId(val value: String)

fun <http://Routing.post|Routing.post>(path: String, handle: (UserId) -> Unit) {
  post(path) {
    val principal = ...
    val userId = ...
    // ... null check + return
    handle(userId)
  }
}

// Then in your routers

post("/api/auth/endpoint") { userId ->
  doSomething(userId)
}
However, if the
userId
claim is always required, you should probably move this check to the
validate
method of the JWT authenticator
e

Eman

04/27/2023, 3:13 PM
...thanks...i will try your suggestion
call is not available?
e

edrd

04/27/2023, 5:59 PM
Change handle to
ApplicationCall.(UserId) -> Unit
Actually, there’s a recursion going on
I think
Yep, you need to import Ktor’s `post`…
e

Eman

04/28/2023, 12:36 PM
image.png
...i don't if this will work?
im ending up extending the ApplicationCall with something like this:
suspend fun ApplicationCall.getUserId(handleUser: (String) -> Unit) {
    val principal = principal<JWTPrincipal>()
    val userId = principal?.getClaim("userId", String::class)
    if (userId == null) {
        respond(
            HttpStatusCode.Forbidden,
            CyrCloError(401, "User not authenticated. Please login in again")
        )
        return@getUserId
    }
    handleUser(userId)
}