Skip to content

Advanced: Action composition

Manabu Nakamura edited this page May 11, 2013 · 2 revisions

Action composition

play2.auth use stackable-controller

Suppose you want to validate a token at every action in order to defeat a [Cross Site Request Forgery](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) attack.

Since it is impractical to perform the validation in all actions, you would define a trait like this:

trait TokenValidateElement extends StackableController {
    self: Controller =>

  private val tokenForm = Form("token" -> text)

  private def validateToken(request: Request[AnyContent]): Boolean = (for {
    tokenInForm <- tokenForm.bindFromRequest(request).value
    tokenInSession <- request.session.get("token")
  } yield tokenInForm == tokenInSession).getOrElse(false)

  override proceed[A](reqest: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Result): Result = {
    if (validateToken(request)) super.proceed(request)(f)
    else BadRequest
  }

}

You can use TokenValidateElement trait with AuthElement trait.

object Application extends Controller with TokenValidateElement with AuthElement with AuthConfigImpl {

  def page1 = StackAction(AuthorityKey -> NormalUser) { implicit request =>
    // do something
    Ok(html.page1("result"))
  }

  def page2 = StackAction(AuthorityKey -> NormalUser) { implicit request =>
    // do something
    Ok(html.page2("result"))
  }

}