Skip to content

Commit

Permalink
Logs unauthorized access to admin route
Browse files Browse the repository at this point in the history
  • Loading branch information
julien-lafont committed Jun 7, 2020
1 parent 511623b commit c854ac5
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions server/src/main/scala/io/mocky/http/middleware/Authorization.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package io.mocky.http.middleware

import cats.data.{ Kleisli, OptionT }
import cats.effect.IO
import io.chrisdavenport.log4cats.SelfAwareStructuredLogger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import org.http4s.implicits._
import org.http4s.server.AuthMiddleware
import org.http4s.{ AuthedRoutes, Request, Response, Status }
Expand All @@ -15,31 +17,41 @@ sealed trait AuthenticationError {
val message: String
val status: Status
}
case class Unauthorized(message: String) extends AuthenticationError {
final case class Unauthorized(message: String) extends AuthenticationError {
val status = Status.Unauthorized
}
case class Forbidden(message: String) extends AuthenticationError {
final case class Forbidden(message: String) extends AuthenticationError {
val status = Status.Forbidden
}

class Authorization(settings: AdminSettings) {

private val logger: SelfAwareStructuredLogger[IO] = Slf4jLogger.getLogger[IO]

/**
* Basic Admin authorization, working by sending a token in `settings.admin.header` header that
* will be matched with `settings.admin.token`
*/
val Administrator = AuthMiddleware(authAdministrator, onFailure)

private def onFailure: AuthedRoutes[AuthenticationError, IO] = {
Kleisli(req => OptionT.liftF(IO.pure(Response[IO](req.context.status).withEntity(req.context.message))))
Kleisli { req =>
OptionT.liftF {
for {
_ <- logger.warn(s"Unauthorized access to ADMIN route: ${req.context.message} from ${req.req}")
response <- IO.pure(Response[IO](req.context.status).withEntity(req.context.message))
} yield response
}
}
}

private def authAdministrator: Kleisli[IO, Request[IO], Either[AuthenticationError, Role]] = Kleisli {
request =>
IO.pure(for {
header <- request.headers.get(settings.header.ci).toRight(
Unauthorized("Couldn't find the authorization header"))
res <- Either.cond(header.value == settings.password, Admin, Forbidden("Invalid token"))
res <- Either.cond(header.value == settings.password, Admin, Forbidden(s"Invalid token '${header.value}'"))
} yield res)
}

}

0 comments on commit c854ac5

Please sign in to comment.