cpe
09/20/2022, 10:13 AMrouting {
get("/test") {
call.respondText("test called")
}
authenticate("auth-jwt") {
route("/featureA") {
get("/") {
val principalSubject = call.principal<JWTPrincipal>()?.subject
featureAService.handleGet(call, principalSubject)
}
post("/") {
val principalSubject = call.principal<JWTPrincipal>()?.subject
featureAService.handlePost(call, principalSubject)
}
put("/") {
val principalSubject = call.principal<JWTPrincipal>()?.subject
featureAService.handlePut(call, principalSubject)
}
}
route("/featureB") {
get("/") {
val principalSubject = call.principal<JWTPrincipal>()?.subject
featureBService.handleGet(call, principalSubject)
}
}
}
}
In this case I’d like to provide the principalSubject to each method (in reality there are a few more context parameters that are shared across those methods like parameters etc.). I don’t want to start each method with retrieving unsers and other context parameters and I also don’t want to repeat those lines in the routing
section. Is there any way to reduce the amount of code here by having some preprocessor (could then use context-receivers
)?August Lilleaas
09/20/2022, 10:21 AMAugust Lilleaas
09/20/2022, 10:23 AMfun myWrapper(
handler: suspend PipelineContext<Unit, ApplicationCall>.(
principalSubject: String?
) -> Unit
): PipelineInterceptor<Unit, ApplicationCall> {
return {
val principalSubject = call.principal<JWTPrincipal>()?.subject
this.handler(principalSubject)
}
}
August Lilleaas
09/20/2022, 10:24 AMget("/foo", myWrapper { principal ->
featureAService.handleFoo(call, principal)
})
Rustam Siniukov
09/20/2022, 10:27 AMcpe
09/20/2022, 10:36 AMRustam Siniukov
09/20/2022, 10:56 AMval plugin = createRouteScopedPlugin("myPlugin") {
on(AuthenticationChecked) { call ->
val data = call.principal.extractData()
call.attributes.put(MyKey, data)
}
}
Rustam Siniukov
09/20/2022, 10:59 AMval ApplicationCall.myAuthData
get() = attributes.get(MyKey)
simon.vergauwen
09/20/2022, 10:59 AMservice.auth { token -> }
, and you can easily switch out implementations in testing as well.August Lilleaas
09/20/2022, 10:59 AMcall.principal<JWTPrincipal>()?.subject
August Lilleaas
09/20/2022, 10:59 AMsimon.vergauwen
09/20/2022, 11:00 AMAugust Lilleaas
09/20/2022, 11:03 AM!!
for that oneAugust Lilleaas
09/20/2022, 11:03 AMsimon.vergauwen
09/20/2022, 11:05 AM!!
anywhere, the errors it throws are much too vague to debug on Grafana. Additionally, I found it confusing to distinct in this way between required -and optional authentication.
Given the small size in which you can wrap Ktor to provide a more meaningful domain DSL is totally worth it for me.simon.vergauwen
09/20/2022, 11:06 AMsuspend
while verifying the JWT tokens, which is not supported in the default authentication validator IIRC.cpe
09/20/2022, 3:05 PMauthentication
/ principal
is null. I installed the plugin in my module section within the embeddedServer
. But when calling
call.principal<JWTPrincipal>()
is null (and there is no principal.extractData()
function).
When I receive the call within my routing
configuration it is set properly and contains a JWTPrincipal
.cpe
09/20/2022, 4:02 PM