scalaplayframeworkdeadbolt-2

deadbolt2 and implicit request


I'm trying to integrate Deadbolt2 into my play framework 2.4 application.

A have following piece of code in my controller

import be.objectify.deadbolt.scala.{ActionBuilders, AuthenticatedRequest, DeadboltActions}
import be.objectify.deadbolt.scala.cache.HandlerCache
import play.api.data.Form
import play.api.data.Forms._
import play.api.mvc.{AnyContent, _}
import modules.user.security.{Authenticator, HandlerKeys, MyDeadboltHandler}

class Login @Inject() (deadbolt: DeadboltActions, handlers: HandlerCache, actionBuilder: ActionBuilders) extends Controller {
    //...
    def login = deadbolt.SubjectNotPresent() {
      Action { implicit request =>
        Ok(login(loginForm))
      }
    }
}

And I got error missing parameter type. I'm following deadbolt examples, which helps me a lot, but I can't figure out how to pass implicit request into action.

My template begins like this:

@(loginForm: Form[LoginForm])(implicit flash: Flash)

Using Action directly without deadbolt.SubjectNotPresent() works well.


Solution

  • One persistent question that keeps coming up is "how do I get the subject in an authorized action?". As of Deadbolt 2.5, the request passed into an action has been replaced with an AuthenticatedRequest which contains an Option[Subject]. As users of 2.4 also want this feature, it has been included in 2.4.4 as a breaking change.

    The following examples use SubjectPresent as an example, but the same change applies to all authorization constraints.

    When using action builders, in place of

    def index = actionBuilder.SubjectPresentAction().defaultHandler() { implicit request
      Ok(accessOk()) 
    }
    

    we now have

    def index = actionBuilder.SubjectPresentAction().defaultHandler() { authRequest =>
      Future {
        Ok(accessOk()) 
      }
    }
    

    When using action composition, in place of

    def index = deadbolt.SubjectPresent() { implicit request
        Action {
            Ok(accessOk())
        }
    }
    

    we now have

    def someFunctionA = deadbolt.SubjectPresent()() { authRequest =>
      Future {
        Ok("Content accessible")
      }
    }
    

    The getSubject() function of the DeadboltHandler trait now takes an AuthenticatedRequest instead of a Request.

    override def getSubject[A](request: AuthenticatedRequest[A]): Future[Option[Subject]] = 
      request.subject match {
        case Some(user) => Future {request.subject}
        case None => // get from database, identity platform, cache, whatever
      }
    

    What this means for your app is

    def login = deadbolt.SubjectNotPresent() {
      Action { implicit request =>
        Ok(login(loginForm))
      }
    }
    

    becomes

    def login = deadbolt.SubjectNotPresent()() { authRequest =>
      Future {
        Ok(login(loginForm))
      }
    }