package models.actions import utils.ConfigHelper import play.api.mvc.{ActionTransformer, Request, WrappedRequest} import scala.concurrent.{Future, ExecutionContext} import scala.util.Try import org.bson.types.ObjectId import pdi.jwt.{JwtJson, JwtAlgorithm, JwtClaim} import play.api.libs.json.Json import javax.inject.Inject class AuthenticationRequest[A](val jwt: String, val requesterId: Option[ObjectId], val isAdmin: Boolean, request: Request[A]) extends WrappedRequest[A](request) /** * The authentication action transformer that transforms the incoming base request to a user request. */ class AuthenticationTransformer @Inject() (implicit val executionContext: ExecutionContext) extends ActionTransformer[Request, AuthenticationRequest] { /** * Transforms the existing request from a Request to UserRequest. * * @param request The incoming request. * @return The new parameter to pass to the Action block. */ override def transform[A](request: Request[A]) = Future.successful { val (jwt: String, requesterId: Option[ObjectId], isAdmin: Boolean) = processJWT(request) new AuthenticationRequest(jwt, requesterId, isAdmin, request) } /** * Processes the JWT token by decoding and validating it. * * @param request The incoming request. * @return The user ID specified in the JWT's payload. */ def processJWT[A](request: Request[A]): (String, Option[ObjectId], Boolean) = { val privateKey = ConfigHelper.getString("jwt.privateKey") try { val authHeader = request.headers.get("Authorization").get val token = authHeader.substring(7) println(s"JWT Token Received: $token") val payload: Try[JwtClaim] = JwtJson.decode(token, privateKey, Seq(JwtAlgorithm.HS256)) val content = payload.get.content val jsonContent = Json.parse(content) val requesterId = (jsonContent \ "userId").as[String] val isAdmin = (jsonContent \ "admin").as[Boolean] (token, Some(new ObjectId(requesterId)), isAdmin) } catch { case ex: Throwable => { println(s"JWT Error: $ex") ("", None, false) } } } }