Play Framework (2) -Security (especially for web application)

Here we talk about how to make our web application much safer. Even though most front-end codes can be detected by any developers, we still can use back-end to protect each request’s security. I will list the method which attackers might be used to hack your system and then I give out basic and simple solution. Here I need to say something in advance: First, the solution here targets play framework. But i think the solution’s idea/view is general for other website framework. Second, because play framework already has multiple versions, i can’t try all of them and here we use 2.3.x . So if you use other play version, please consider how to implement solution in your own version. All in all, I will give out problem first and talk about my solution’s idea, and at last give code snippet to explain idea.

1. problem

we all know front-end uses router to connect with back-end in order to get some data or post data to store. Once the router is recognized by attacker. It is quite easy for other developers to send requests to back-end without requiring to login the system or in website. There are many public tools which can do this thing, like postman, etc.

2. solution

The solution is easy to think out: authentication. The authentication is already greatly used in many places and there are many mature libraries which already provide packaged class/object to call, like social-auth, play2-auth, etc.

But there are too complex, if you want simpler one, you just need to consider how to make sure “Action” is safe in your code. As we all know, each router mapping to back-end is Action, no matter GET or POST. If we can make sure “Action” is a safe action, our router is safe. So we try to re-define a double check Action which needs to check each request’s header whether it contains the authenticated info. If not, we treat this request is not authenticated, the request can’t be finished. For browser, this means the page needs to guide back to login page to force user login or signup. Only when user logins or signs up, we assign the authentication to the user. After the user is authenticated, the other requests are allowed from this user.

Here we list the logic:

  1. user login/signup, back-end will set the user authenticated
  2. user does other requests, back-end will treat it as authenticated
  3. if user not login/signup or already logout, the next request will be treated as unauthenticated, 401 will be returned.

3. code snippet

Define a useraction:

package controllers

import play.api.http.Status
import play.api.mvc._

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object UserAction extends ActionBuilder[Request] {
  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    if (request.session.get("WWW-Authenticate").isDefined)
      block(request)
    else
      Future { Results.Status(Status.UNAUTHORIZED) }
  }
}

Login/signup with an authentication:

Ok(resultInfo).withSession("WWW-Authenticate" -> "user")

Logout:

Ok.withNewSession

Other router using defined useraction:

/**
 * Delete one user back to front-end
 */
def delete = UserAction {
  request => {
      // do your things
    }
  }
}

4. Additional Info

(1) CSRF(cross-site-request-forgery)

Problem: If the attacker uses false info to signup, he/she still can use this authenticated user to do some dangerous things.

Solution: Of course, we can assign different levels of authentication. For example, for admin operations, only use who knows admin’s right or has admin’s authentication, he/she can obtain the operation.

But there is another easy way to solve it: filter.

To allow simple protection for non browser requests, such as requests made through AJAX, Play also supports the following:

  • If an X-Requested-With header is present, Play will consider the request safe. X-Requested-With is added to requests by many popular Javascript libraries, such as jQuery.
  • If a Csrf-Token header with value nocheck is present, or with a valid CSRF token, Play will consider the request safe.

(2) ActionBuilder

Action is just an implementation of ActionBuilder[Request]; we can extend ActionBuilder to use in place of Action as above codes in snippet.

ActionBuilder requires that we implement invokeBlock, which takes two parameters, the first is the incoming request, and the second is the function body, taking Request[A] as a parameter and returning a Future[Result]

block(request) means request processing continues as expected. (Don’t confuse the world “block” to mean the request gets blocked, it is actually executing the code block or function body it was passed earlier)

5. Recommend Links

(1) Here is link about how to use play header to fix CSRF: https://www.playframework.com/documentation/2.3.x/ScalaCsrf 

(2) Action Composition in Play Framework: https://www.playframework.com/documentation/2.3.x/ScalaActionsComposition and http://iankent.uk/2014/02/10/action-composition-in-play-framework/ (this link’s knowledge is a little old, but really useful and completely. And it also provides more integral solution than mine. Strongly suggest to read. )

 

 

Advertisements

One thought on “Play Framework (2) -Security (especially for web application)

  1. Pingback: Cookie by Scala | Play Harder, Work Harder

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s