Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use subject claim from jwt #131

Merged
merged 4 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions app/controllers/auth/JWTJsonAuthenticatedAction.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package controllers.auth

import com.google.inject.Inject
import com.jayway.jsonpath.JsonPath
import net.minidev.json.JSONArray
import pdi.jwt.{JwtAlgorithm, JwtClaim, JwtJson}
Expand All @@ -9,7 +10,7 @@ import play.api.{Configuration, Logging}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success, Try}

class JWTJsonAuthenticatedAction(parser: BodyParsers.Default, appConfig: Configuration)(implicit ec: ExecutionContext)
class JWTJsonAuthenticatedAction @Inject()(parser: BodyParsers.Default, appConfig: Configuration)(implicit ec: ExecutionContext)
extends ActionBuilderImpl(parser) with Logging {

logger.debug("In JWTJsonAuthenticatedAction")
Expand Down Expand Up @@ -66,6 +67,12 @@ class JWTJsonAuthenticatedAction(parser: BodyParsers.Default, appConfig: Configu
} else true
}

private def getUserRequestIfAvailable[A](token: JwtClaim, request: Request[A]): Request[A] = {
if (token.subject.isDefined) {
UserRequest(token.subject.get, request)
} else request
}
jclapadula marked this conversation as resolved.
Show resolved Hide resolved

private def redirectToLoginPage(): Future[Result] = {
Future {
Results.Redirect(JWT_LOGIN_URL)
Expand All @@ -79,7 +86,7 @@ class JWTJsonAuthenticatedAction(parser: BodyParsers.Default, appConfig: Configu
getJwtCookie(request) match {
case Some(cookie) =>
isAuthenticated(cookie.value) match {
case Some(token) if isAuthorized(token.content) => block(request)
case Some(token) if isAuthorized(token.content) => block(getUserRequestIfAvailable(token, request))
case _ => redirectToLoginPage()
}
case None => redirectToLoginPage()
Expand Down
55 changes: 46 additions & 9 deletions test/auth/JWTJsonAuthenticatedActionSpec.scala
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package auth

import java.security.{KeyPairGenerator, SecureRandom}
import java.util.Base64

import controllers.auth.{JWTJsonAuthenticatedAction, UserRequest}
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.mockito.MockitoSugar
import org.scalatestplus.play.PlaySpec
import org.scalatestplus.play.guice.GuiceOneAppPerTest
import pdi.jwt.{JwtAlgorithm, JwtJson}
import play.api.db.{Database, Databases}
import play.api.{Application, Mode}
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.json.Json
import play.api.mvc.{Cookie, Result}
import play.api.libs.json.{JsString, Json}
import play.api.mvc.{Cookie, Request, Result, Results}
import play.api.test.FakeRequest
import play.api.test.Helpers._
import play.api.{Application, Mode}

import scala.concurrent.Future
import java.security.{KeyPairGenerator, SecureRandom}
import java.util.Base64
import scala.concurrent.{ExecutionContext, Future}

class JWTJsonAuthenticatedActionSpec extends PlaySpec with MockitoSugar with GuiceOneAppPerTest with ScalaFutures {

Expand Down Expand Up @@ -143,6 +143,40 @@ class JWTJsonAuthenticatedActionSpec extends PlaySpec with MockitoSugar with Gui
result.header.status mustBe 200
}
}

"return a UserRequest if the subject claim is present" in {
val userName = "test_user"
val request = FakeRequest(GET, "/api/v1/allRulesTxtFiles")
.withCookies(buildJWTCookie(userName, Seq("search-manager")))
var authenticator = app.injector.instanceOf[JWTJsonAuthenticatedAction]
jclapadula marked this conversation as resolved.
Show resolved Hide resolved
var modifiedRequest: Request[Any] = request;

var authenticated = authenticator.invokeBlock(request, (receivedRequest: Request[Any]) => {
modifiedRequest = receivedRequest
Future.apply(Results.Ok)(ExecutionContext.global)
jclapadula marked this conversation as resolved.
Show resolved Hide resolved
})

whenReady(authenticated) { _ =>
modifiedRequest mustBe a[UserRequest[Any]]
}
}

"not touch the request if the subject claim is not present" in {
val request = FakeRequest(GET, "/api/v1/allRulesTxtFiles")
.withCookies(buildJWTCookie(null, Seq("search-manager")))
var authenticator = app.injector.instanceOf[JWTJsonAuthenticatedAction]
var modifiedRequest: Request[Any] = request;

var authenticated = authenticator.invokeBlock(request, (receivedRequest: Request[Any]) => {
modifiedRequest = receivedRequest
Future.apply(Results.Ok)(ExecutionContext.global)
})

whenReady(authenticated) { _ =>
modifiedRequest mustBe request
modifiedRequest must not be a[UserRequest[Any]]
}
}
}

private def generateRsaKeyPair() = {
Expand All @@ -151,8 +185,11 @@ class JWTJsonAuthenticatedActionSpec extends PlaySpec with MockitoSugar with Gui
keyGen.generateKeyPair()
}

private def buildJWTCookie(userName: String, roles: Seq[String], value: Option[String] = None): Cookie = {
val token = Json.obj(("roles", roles), ("user", userName))
private def buildJWTCookie(userName: String, roles: Seq[String] = Seq.empty, value: Option[String] = None): Cookie = {
jclapadula marked this conversation as resolved.
Show resolved Hide resolved
var token = Json.obj(("roles", roles))
if (userName != null) {
token = token + ("sub", JsString(userName))
}

Cookie(
name = getJwtConfiguration("cookie.name"),
Expand Down