Concrete request body for Authorization logic


A new Silhouette user here!

I’m trying to use Silhouette for Authorization as well as Authentication in my application.
I’ve run into the following problem, hoping someone here can help.

For authorizing consumers of my API endpoints, I extend the Authorization[I <: Identity, A <: Authenticator] trait.
Overriding its method def isAuthorized[B](identity: I, authenticator: A)(implicit request: Request[B]): Future[Boolean] is simple enough.
The problem is B. My authorization logic depends on the body of the request i.e. B. I want to be able to use a concrete type there, so that I can do something like:

override def isAuthorized[Foo](user: User, authenticator: A) (implicit request: Request[Foo]): Future[Boolean] = { Future.successful(request.body.fooField) }

Here Foo is a case class that contains the field fooField, i.e. what the body of my request deserializes to.
The documentation for this method mentions: @tparam B The type of the request body so I am assuming I can actually use my case class as B (not sure if a case class counts as a type here, I’m new to Scala too!).

My method definition above fails to compile. i.e. I cannot use request.body.fooField inside my method.
Compilation error is: value fooField is not a member of type parameter Foo

What also caught my eye is the Foo import statement is considered unused. This means that Foo in isAuthorized[Foo] is not even my case class Foo. I suspect that this has something to do with case class not being a type.

Can someone help me out here? How can I get my request body deserialized and available for the authorization check?

Thank you.



you have defined Foo as type parameter of isAuthorized. So it won’t import your Foo case class, because you have defined a type Foo in your scope. It would also not possible to change the signature of your concrete implementation, because then you could not pass it to the action. Normally, you should pattern match on the request body which is currently also not possible because of the type erasure limitation. To get this to work we must define an implicit class tag for type B. I’ll see if I can create a pull request in the next days, which would allow a pattern match on the request body.

Best regards



Adding a TypeTag to the Authorization trait is a really big surgery in the current system. Could you please describe what do you try to achieve? Do you really create a new content type? Normally Play has built-in all the needed content types to handle all the thinkable request methods/types? Why do you not deserialize your body inside the authorization handler to your Foo class?


This is what I am trying to do. I am not trying to create a new content type or anything. My incoming JSON maps correctly to the Foo class and my authorization logic depends on a field in that class as well. So I want to deserialize request.body to the Foo class in the Authorization implementation.



Have you tried something like this?

import play.api.libs.json.{ Format, Json }
import play.api.mvc.{ AnyContentAsJson, Request }

import scala.concurrent.Future

case class Foo(fooField: String)
object Foo {
  implicit val jsonFormat: Format[Foo] = Json.format[Foo]

case class FooAuthorization() extends Authorization[User, CookieAuthenticator] {
  def isAuthorized[B](user: User, authenticator: CookieAuthenticator)(
    implicit request: Request[B]): Future[Boolean] = {

    Future.successful(request.body match {
      case AnyContentAsJson(json) => json.asOpt[Foo] match {
        case Some(foo) => foo.fooField == "test"
        case None => false
      case _ => throw new RuntimeException("Wrong content type")