Skip to content

Instantly share code, notes, and snippets.

@domdorn
Created August 14, 2019 10:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save domdorn/0babae52f9a96b1db6e38aa77690edbf to your computer and use it in GitHub Desktop.
Save domdorn/0babae52f9a96b1db6e38aa77690edbf to your computer and use it in GitHub Desktop.
package com.dominikdorn.common.authentication
import com.dominikdorn.commons.scala.play.security.Authenticator
import play.api.mvc.{Action, ControllerComponents, Handler, RequestHeader, Results}
import play.api.routing.Router.Routes
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration._
// this is like a filter, but works on a Routes instead of all requests.
// I'll have to check with the PlayFramework-Core team on how to solve the "Future" issue.
class OperationsRoutesDecorator(routes: Routes, authenticator: Authenticator, cc: ControllerComponents)(
implicit val ec: ExecutionContext)
extends Routes {
private[this] val forbiddenHandler = cc.actionBuilder.apply { r =>
Results.Forbidden("Your JWT does not have the required audience/scope for this request.")
}
override def isDefinedAt(x: RequestHeader): Boolean = routes.isDefinedAt(x)
override def apply(request: RequestHeader): Handler = {
val maybeToken = request.headers
.get("Authorization")
.filter(_.toLowerCase.startsWith("bearer "))
.map(_.split(" ").last)
val authInfo = maybeToken match {
case Some(token) => authenticator.authenticate(token)
case None => Future.successful(None)
}
val isWrite = request.method match {
case "POST" => true
case "PUT" => true
case "DELETE" => true
case _ => false
}
val isOptions = request.method == "OPTIONS"
val isRead = request.method == "GET"
val f: Future[Handler] = authInfo.map {
case Some(a)
if isWrite && a.audience.contains("https://shop.api.dominikdorn.com") && a.scope.contains("operations:write") =>
routes.apply(request)
case Some(a) if isOptions => routes.apply(request)
case Some(a)
if isRead && a.audience.contains("https://shop.api.dominikdorn.com") && a.scope.contains("operations:read") =>
routes.apply(request)
case _ => forbiddenHandler
}
val handler: Handler = Await.result(f, 100.seconds) // need to find a solution for this.
handler
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment