How to install a feature after Authentication phas...
# ktor
v
How to install a feature after Authentication phase so I can use a Principal? Tried this without success:
Copy code
companion object Feature : ApplicationFeature<ApplicationCallPipeline, Configuration, Permission> {
        override val key = AttributeKey<Permission>("Permissions")

        override fun install(pipeline: ApplicationCallPipeline, configure: Configuration.() -> Unit): Permission {
            val configuration = Configuration().apply(configure)
            val feature = Permission(configuration)
            val permissionPhase = PipelinePhase("PermissionPhase")

            pipeline.insertPhaseAfter(PipelinePhase("RequestAuthentication"), permissionPhase)


            pipeline.intercept(permissionPhase) {
                feature.intercept(this)
            }

            return feature
        }
    }
👆 1
e
The Authentication feature defines its own pipeline stages as part of the
AuthenticationPipeline
companion object. You can retrieve the authentication pipeline from your provider definition, e.g.:
Copy code
install(Authentication) {
  jwt {
    val newPhase = PipelinePhase("myPhase")
      pipeline.insertPhaseAfter(AuthenticationPipeline.RequestAuthentication, newPhase)
    pipeline.intercept(newPhase) { /* your code here... */ }
  }
}
See: https://github.com/ktorio/ktor/blob/master/ktor-features/ktor-auth/jvm/src/io/ktor/auth/AuthenticationPipeline.kt https://github.com/ktorio/ktor/blob/master/ktor-features/ktor-auth/jvm/src/io/ktor/auth/AuthenticationProvider.kt
Note that this is just a guess based on the Auth feature source code.
👍 1
v
Hey Evan! I did it, but still gets executed before the jwt.validade{...}
Copy code
install(Authentication) {
        jwt {
            verifier(JWTConfig("secret").verifier)
            validate {
                val loggedInUser = LoggedInUser(
                    idCliente = UUID.fromString(it.payload.subject),
                    id = UUID.fromString(it.payload.getClaim("uid").asString()),
                    active = it.payload.getClaim("atv").asBoolean(),
                    admin = it.payload.getClaim("adm").asBoolean(),
                    canEdit = it.payload.getClaim("edt").asBoolean(),
                    canDelete = it.payload.getClaim("del").asBoolean()
                )
                loggedInUser
            }

            val permissionPhase = PipelinePhase("PermissionPhase")
            pipeline.insertPhaseAfter(AuthenticationPipeline.RequestAuthentication, permissionPhase)
            pipeline.intercept(permissionPhase) {
                call.authentication.principal<LoggedInUser>()?.let {
                    if (!it.active) httpException(
                        code = HttpStatusCode.Forbidden,
                        developerMessage = "User not active",
                        userMerssage = "Usuario não está ativo"
                    )

                    when (call.request.local.method) {
                        <http://HttpMethod.Post|HttpMethod.Post> -> if (!it.canEdit) httpException(
                            code = HttpStatusCode.Forbidden,
                            developerMessage = "User cannot edit",
                            userMerssage = "Usuario não pode editar"
                        )
                        HttpMethod.Put -> if (!it.canEdit) httpException(
                            code = HttpStatusCode.Forbidden,
                            developerMessage = "User cannot edit",
                            userMerssage = "Usuario não pode editar"
                        )
                        HttpMethod.Delete -> if (!it.canDelete) httpException(
                            code = HttpStatusCode.Forbidden,
                            developerMessage = "User cannot delete",
                            userMerssage = "Usuario não pode excluir"
                        )
                    }
                }
            }
        }
    }