Showing posts with label Play. Show all posts
Showing posts with label Play. Show all posts

Thursday, August 29, 2013

CSRF protection in a Play+AngularJS application

From Wikipedia:
Cross-site request forgery, also known as a one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf[1]) or XSRF, is a type of malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts.[2] Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser.
There are plenty of articles online explaining such attacks and measures against them. The basic idea of such protection is to generate a CSRF token per session and send that token in every following request through means other than the Cookie request header (because it's the one that browser automatically set and hence the vulnerability). Typically the token can be sent back in a custom request header or in the request query string or an hidden input value in forms. Play has a built-in filter that implements such token based CSFR protection(here is a great blog article about it). However it's based on html form(with automatic query string generation). In a single-page application that relies on Play as a pure server-side API, most requests are performed by AJAX without involving html form. In that case CSRF token has to be sent through a custom request header. Our application uses AngularJS as our front-end framework. AngularJS also provides some facility to guard against CSRF (from AngularJS' documentation):
Angular provides a mechanism to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain could read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. The header will not be set for cross-domain requests. To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called XSRF-TOKEN on the first HTTP GET request. On subsequent XHR requests the server can verify that the cookie matches X-XSRF-TOKEN HTTP header, and therefore be sure that only JavaScript running on your domain could have sent the request.
So putting pieces together here is our implementation for CSFR protection in an AngularJS + Play application. The AngularJS side is automatic, so the work is at the play side to set token in the cookie and validate it.

When login succeeds, set the cookie that AngularJS consumers:
    Ok.withSession(("username" -> username).
       withCookies(Cookie("XSRF-TOKEN", createCSFRToken(username), httpOnly = false))
createCSFRToken is a function that hashes the username to a token so that the token is not reconstructible by attackers. httpOnly = true is there so that the cookie is readable by javascript (from the same domain of course).

For the following requests, here is the code to validate the token sent in the custom header (automatically set by AngularJS):
  def validateSessionUser(implicit request: RequestHeader): Option[String] = {
    request.session.get("username").filter { username =>
      request.headers.get("X-XSRF-TOKEN") == Some(createCSFRToken(username))
    }
  }
That's it. Feel free to ask any question in the comments.

Saturday, May 25, 2013

Case class enumeration in Play 2.1 Application (on top of Salat/MongoDB)

Recently in our Play 2.1(Scala) application I needed to implement a model that's like Java enum. Since scala's Enumeration class doesn't have a fantastic reputation, I decided to go with the case class approach. Our Play 2.1 application is a JSON REST API that sits on top of MongoDB, so I need to make sure that this model can have both JSON and MongoDBObject serialization wired up.
Let's start from Enum base trait
trait Enum[A] {
  trait Value { self: A => }
  val values: List[A]
  def parse(v: String) : Option[A] = values.find(_.toString() == v)
}
We'll see the use of the parse function later.

In our system we have a flag system for content entries. Here is the flag case class enum.
import com.novus.salat.annotations._

@Salat
sealed trait Flag extends Flag.Value

case object DEPRESSING extends Flag
case object VIOLENCE extends Flag
case object NSFW extends Flag

object Flag extends Enum[Flag] with SimpleEnumJson[Flag] {
  val values = List(DEPRESSING, VIOLENCE, NSFW)
}
The @Salat is needed for salat to map abstract class inheritance tree. SimpleEnumJson[T] is the one that provides Play 2.1 JSON API formats which you will need for JSON serialization. Here is its implementation.
import play.api.libs.json._

trait SimpleEnumJson[A] {
  self: Enum[A] =>

  implicit def reads: Reads[A] = new Reads[A] {
    def reads(json: JsValue): JsResult[A] = json match {
      case JsString(v) => parse(v) match {
        case Some(a) => JsSuccess(a)
        case _ => JsError(s"String value ($v) is not a valid enum item ")
      }
      case _ => JsError("String value expected")
    }
  }

  implicit def writes[A]: Writes[A] = new Writes[A] {
    def writes(v: A): JsValue = JsString(v.toString)
  }
}
As the name suggests, SimpleEnumJson uses the simple toString() of the enum item for JSON representation.
Note that we could place the items definitions inside the companion object, but unfortunately salat couldn't map the class that way.
This should be good enough for most cases, a simple case class based enum that can be used in any models.
Now let's make it a little more complex, let's say we need one more attribute in our Flag class: age rating - each flag indicates that the content is only appropriate for users above a certain age.
@Salat
sealed trait Flag extends Flag.Value {
  val ageRating : Int
}
case object DEPRESSING extends Flag { val ageRating = 18 }
case object VIOLENCE extends Flag { val ageRating = 16 }
case object NSFW extends Flag { val ageRating = 21 }
Now we need a bit more work for our JSON reads/writes, the SimpleEnumJSON[T] is no longer sufficient. Let's write a CompositeEnumJSON[T]
trait CompositeEnumJson[A] {
  self: Enum[A] =>
  implicit val reads = (__ \ 'name).read[String].map( parse(_).get )
  val nameWrite = (__ \ 'name).write[String]
  implicit val writes : OWrites[A]
}
Here we map a composite case class enum into a JsObject with a name field that holds the toString() value of the item. When we read from JSON, we only need the "name" field. We need concrete inheriting case class to implement the Json write:
object Flag extends Enum[Flag] with CompositeEnumJson[Flag] {
  val values = List(DEPRESSING, VIOLENCE, NSFW)
  implicit val writes : OWrites[Flag] = (
    nameWrite ~
    (__ \ 'ageRating).write[Int]
  )(unlift(unapply))

  def unapply(flag: Flag) = {
    Some(( flag.toString(), flag.ageRating ))
  }
}
There you have it - a composite case class based enum that can have attributes.
I hope you find this helpful and let me know if you have any suggestion for improvements.

Tuesday, May 07, 2013

Define arbitrary tasks in the Play 2.1 Framework (Rakes like)

Recently with the help from James Roper from Typesafe, I added some arbitrary tasks to our application so that we can seed some data from command line. These tasks are basically like rake tasks in which you can run fire up the application environment and perform code written for you application.

The idea is to create SBT tasks and then, quoted from James, "get a hold of the dependencies, create a new URLClassLoader with them, load the class you want to use from that classloader using reflection, and then invoke it."

Here is the code in the SBT build file Build.scala
import java.net.URLClassLoader
object ApplicationBuild extends Build {
//Other project settings such as appVersion and appDependencies

def registerTask(name: String, taskClass: String, description: String) = {
  val sbtTask = (dependencyClasspath in Runtime) map { (deps) =>
    val depURLs = deps.map(_.data.toURI.toURL).toArray
    val classLoader = new URLClassLoader(depURLs, null)
    val task = classLoader.
                 loadClass(taskClass).
                 newInstance().
                 asInstanceOf[Runnable]
    task.run()
  }
  TaskKey[Unit](name, description) <<= sbtTask.dependsOn(compile in Compile)
}

val main = play.Project(appName, appVersion, appDependencies).settings(
  registerTask("seed-data-book","tasks.SeedBooks", "seed for book table" ),
  registerTask("seed-data-user","tasks.SeedUsers", "seed for user table" )
)

Here is our task classes (I placed it in app/tasks)
package tasks
import play.core.StaticApplication

abstract class Task extends Runnable { 
  val application = new StaticApplication(new java.io.File("."))
}
    
class SeedBooks extends Task{
  def run {
    Book.dao.save(new Book("Introduction to Scala", "Martin Odersky"))
  }
}
    
class SeedUsers extends Task{
  def run {
    User.dao.save(new User("jRoper", "password"))
  }
}
I hope this helps. Feel free to ask any questions in the comments.