playframeworkoauth-2.0actionbuilder

Adding ActionBuilders to a project to check permissions after identification


First of all, I'm a newbie in Play Framework, so maybe this is very basic, but I couldn't find enough documentation to clarify.

Currently I have a project that use Oauth2 to identify and authorize the users. This is being done with an ActionBuilder and working well.

What I do want now is an aditional "layer", this means, after authorizing, check if the user has enough permissions (permission table is stored in DB).

I've read about Action Composition, but since I'm using ActionBuilder I think I should be able to do it with them. I've seen composeAction function, but I'm not pretty sure about how to implement this.

My code, currently looks like:

case class AuthenticatedRequest[A](user: User, request: Request[A]) extends WrappedRequest(request)

  def authenticate[A](block: AuthenticatedRequest[A] => Future[Result])(implicit request: Request[A]) = {
    authorize(new OauthDataHandler()) { authInfo =>
      block(AuthenticatedRequest(authInfo.user, request))
    }
  }

  object Authenticated extends api.mvc.ActionBuilder[AuthenticatedRequest]  {

    def invokeBlock[A](request: Request[A], block: AuthenticatedRequest[A] => Future[Result]) = {
      authenticate(block)(request)
    }
  }
}

And my attempt right now is this:

case class PermissionAuthenticatedRequest[A](user: User, zone: String, request: Request[A]) extends WrappedRequest(request)

  object PermissionAuthenticated extends api.mvc.ActionBuilder[PermissionAuthenticatedRequest] {
    def invokeBlock[A](request: Request[A], block: PermissionAuthenticatedRequest[A] => Future[Result]) = {

      checkPermissions(???/*user*/, ???/*zone*/,block)(request)
    }

    def checkPermissions[A](user: User, permission: String, block: PermissionAuthenticatedRequest[A] => Future[Result])(implicit request: Request[A]) = {
        if(user._id == 1) //silly check
          block(PermissionAuthenticatedRequest(user, permission, request)) 
        else 
          Future.successful(Forbidden)
    }
  }

But I still don't know how to retrieve the user (from other AuthenticatedAction) or privilege (from the request).

Thank you in advance.


Solution

  • w, scala-oauth2-provider 0.13.1 has AuthorizedAction. so you can authenticate as follows

    import scalaoauth2.provider.OAuth2ProviderActionBuilders._
    
    object YourController extends Controller {
      def index = AuthorizedAction(new OauthDataHandler()) { req =>
        req.authInfo // you can take AuthInfo
        ...
      }
    }
    

    And all you need is create a permission check ActionFilter

    import scalaoauth2.provider._
    
    object PermissionActionFilter extends ActionFilter[({type L[A] = AuthInfoRequest[User, A]})#L] {
    
      protected def filter[A](request: AuthInfoRequest[User, A]): Future[Option[Result]] = Future.successful {
         request.authInfo.user // you can take AuthInfo
         if (user._id == 1) //silly check {
           None
         } else {
           Some(Forbidden)
         }
      }
    }
    

    you can use PermissionActionFilter as follows

    object YourController extends Controller {
    
      val MyAction = AuthorizedAction(new OauthDataHandler()) andThen PermissionActionFilter
    
      def index = MyAction { req =>
        req.authInfo // you can take AuthInfo
        ...
      }
    }