kotlinquarkusunauthorizedquarkus-reactive

How to customize Unauthorized response in Quarkus?


Because we use a custom format of error we want to customize all error responses ... in particular Forbidden (we succeed) and Unauthorized (we failed).

I read many docs, posts and I tried different solutions you can find in my sample project

First: ServerExceptionMapper

@ServerExceptionMapper
@Priority(1)
fun unauthorized(e: UnauthorizedException) =
   mapExceptionIntoError(Response.Status.UNAUTHORIZED, "UNAUTHORIZED", e.message)

Second: ExceptionMapper

@Provider
@Priority(Priorities.AUTHORIZATION)
class UnauthorizedErrorMapper : ExceptionMapper<UnauthorizedException> {

    private val logger: Logger = Logger.getLogger(this.javaClass.simpleName)

    @Override
    override fun toResponse(exception: UnauthorizedException): Response {
        logger.severe(exception.message)

        val message = exception.message
        val code = STATUS.statusCode
        val error =  ErrorInfo(STATUS.statusCode, STATUS.name, message)

        return Response
            .status(code)
            .entity(error)
            .build()
    }

    companion object {
        private val STATUS = Response.Status.UNAUTHORIZED
    }
}

Third: failureHandler

@ApplicationScoped
class UnauthorizedExceptionHandler {
    fun init(@Observes router: Router) {
        router.route().failureHandler { event ->
            if (event.failure() is UnauthorizedException) {
                event.response().end("CUSTOMIZED_RESPONSE")
            } else {
                event.next()
            }
        }
    }
}

With no success. What did I miss or do wrong?

Thanks in advance Patrice


Solution

  • ServerExceptionMapper works only for /hello using RolesAllowed annotation like in

        @GET
        @Path("/hello")
        @RolesAllowed("role1")
        fun hello(): RestResponse<Reply> = RestResponse.ok(Reply("Hello from RESTEasy Reactive"))
    
    
        @GET
        @Path("/helloNotAnnotated")
        @Produces(MediaType.APPLICATION_JSON)
        fun helloNotAnnotated() = RestResponse.ok(Reply("Hello from helloNotAnnotated"))
    
    

    and not for role2 defined in application.properties using elytron

    quarkus.security.users.embedded.enabled=true
    quarkus.security.users.embedded.plain-text=true
    quarkus.security.users.embedded.users.user=password
    quarkus.security.users.embedded.roles.role1=user
    quarkus.security.users.embedded.roles.role2=user
    quarkus.http.auth.permission.role-role2.paths=/helloNotAnnotated
    quarkus.http.auth.permission.role-role2.policy=role2-policy
    quarkus.http.auth.policy.role2-policy.roles-allowed=role2
    

    See differences in action in my sample project