-
-
Save domdorn/0babae52f9a96b1db6e38aa77690edbf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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