scalaplayframeworkdeadbolt-2

Deadbolt authorization based on parameters


I am testing Deadbolt in a Scala Play Application. My controller methods look something like this:

def getProject(projectId: Int) = actionBuilder.RestrictAction("user").defaultHandler()  {
    authRequest =>
    //retrieves project
}

In this case, I only want the user to be authorized to get the project if the projectId belongs to this user. Other more complex cases involve multiple parameters both from the query string and/or the post body.

From what I understand, the approach here would be to pass the parameters to a DynamicResourceHandler and then handling the permissions for each case individually. It is feasible, but I was expecting a bit more support from Deadbolt for this use case. What is the best approach to authorize a request based on the parameters received?


Solution

  • Deadbolt stays fairly neutral to avoid forcing developers into a specific style, but in this case you can use the meta argument to pass the information into the constraint. The definition is

      object DynamicAction {
    
        def apply(name: String, meta: Option[Any] = None): DynamicAction.DynamicActionBuilder = DynamicActionBuilder(name, meta)
    
        case class DynamicActionBuilder(name: String, meta: Option[Any] = None) extends DeadboltActionBuilder {
    
          override def apply[A](bodyParser: BodyParser[A])(block: AuthenticatedRequest[A] => Future[Result])(implicit handler: DeadboltHandler) : Action[A] =
            deadboltActions.Dynamic(name, meta, handler)(bodyParser)(block)
        }
      }
    

    so your controller function will look something like this

    def getProject(projectId: Int) = actionBuilder.DynamicAction(name = "checkProject", meta = Some(projectId)).defaultHandler()  {
        authRequest =>
        //retrieves project
    }
    

    This will get a DynamicResourceHandler (I've come to hate that name, I may change it in some future version) and invoke your implementation of this function

      def isAllowed[A](name: String,
                       meta: Option[Any] = None,
                       deadboltHandler: DeadboltHandler,
                       request: AuthenticatedRequest[A]): Future[Boolean]
    

    You will need to use asInstanceOf for the meta value.

    For more complex requirements, you can pass whatever you have assembled the data into (a case class or map, for example) as the meta argument.