All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zalando.zhewbacca.SecurityRule.scala Maven / Gradle / Ivy

The newest version!
package org.zalando.zhewbacca

import org.zalando.zhewbacca.TokenInfoConverter._
import play.api.Logger
import play.api.mvc.{RequestHeader, Result, Results}

import scala.concurrent.{ExecutionContext, Future}

trait SecurityRule {
  def isApplicableTo(requestHeader: RequestHeader): Boolean
  def execute(nextFilter: (RequestHeader) => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result]
}

abstract class StrictRule(method: String, pathRegex: String) extends SecurityRule {

  private val RequestMatcherRegex = s"^$method $pathRegex$$".r

  def isApplicableTo(requestHeader: RequestHeader): Boolean =
    RequestMatcherRegex.pattern.matcher(s"${requestHeader.method} ${requestHeader.uri}").matches

}

abstract case class ValidateTokenRule(
    method: String,
    pathRegex: String,
    scope: Scope
) extends StrictRule(method, pathRegex) {

  def authProvider: AuthProvider

  override def execute(nextFilter: (RequestHeader) => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result] =
    RequestValidator.validate(scope, requestHeader, authProvider).flatMap[Result] {
      case Right(tokenInfo) =>
        Logger.info(s"Request #${requestHeader.id} authenticated as: ${tokenInfo.userUid}")
        nextFilter(requestHeader.withTokenInfo(tokenInfo))

      case Left(result) =>
        Logger.info(s"Request #${requestHeader.id} failed auth")
        Future.successful(result)
    }
}

/**
  * Allowed to 'pass-through' of any request. It means that no security checks will be applied.
  * It is often useful in combination with 'catch all' rule which forces to verify tokens for all endpoints.
  */
case class ExplicitlyAllowedRule(method: String, pathRegex: String) extends StrictRule(method, pathRegex) {

  override def execute(nextFilter: (RequestHeader) => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result] =
    nextFilter(requestHeader)

}

/**
  * Useful for explicitly denied HTTP methods or URIs.
  */
case class ExplicitlyDeniedRule(method: String, pathRegex: String) extends StrictRule(method, pathRegex) {

  override def execute(nextFilter: (RequestHeader) => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result] =
    Future.successful(Results.Forbidden)
}

/**
  * Default rule for `SecurityFilter`.
  */
class DenyAllRule extends SecurityRule {

  override def isApplicableTo(requestHeader: RequestHeader): Boolean = true

  override def execute(nextFilter: (RequestHeader) => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result] =
    Future.successful(Results.Forbidden)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy