Blog

A method to protect web pages using HTTPS redirects in a Play Framework application.

Rijware Blog Securing Play

Using Play Framework’s Action Composition feature to enforce HTTPS access

Often it is necessary to protect data exchanged between your website and your users’ browsers. Protected data exchange can be required by all or part of your website and can be fulfilled with HTTPS. Part of building in this protection is forcing secure pages to be accessed using HTTPS while disallowing HTTP access.

One way to accomplish this is to redirect any HTTP access attempts to HTTPS. In a Play Framework application this can be done by using action composition where a redirect action is placed in front of an application controller. This example works with a Java based Play Framework version 2.2.0 application.

Consider a website that has several public pages that are accessible over HTTP and a set of administrative pages that are protected by a login and can only be accessed over HTTPS. While both sets of pages could be managed by a single controller using method level actions, in this example we will allocate the public pages to a main application controller, PublicController, and the protected administrative pages to an AdminController.

PlaySSLwKey

In our example the AdminController is responsible for 3 pages:

Login – a login page, where a user and password are entered

Users – a page listing configured users

EditUser – a page for editing user information

In order to force HTTPS access to these pages we add an action called HttpsAction to the AdminController. So, we have a class that looks like this:

 Figure 1:  AdminController class

In the above AdminController class, the annotation @With(HttpsAction.class) is used to force HTTPS redirection for all pages the controller provides. Notice that methods requiring that the user be logged on (authenticated) are annotated with @Security.Authenticated to force a check before executing the method. The details of authentication will not be discussed here, but can be found in the Play Framework samples. The HttpsAction class, shown below, is a Simple action extension. It examines each request to determine whether it was received over HTTPS. If the request came in over HTTPS, it is simply delegated to the appropriate controller method. If it did not come in by HTTPS, it is redirected to the original URI, but over HTTPS. Two cases are considered, one for production and one for development. In the production case, it is assumed that the web server is using the standard port 443 for HTTPS, while in the development scenario, a port is configured for HTTPS.

In the production case, how does the HttpsAction determine whether the request is using HTTPS? This is not completely straightforward since the Request object provided in the Context does not indicate if the request was received over HTTPS. The URI can’t be examined to determine if the inbound port was 443 since the default port isn’t always specified in the request. Ideally, a newer version of the framework will propagate the scheme or a “secure” flag in the Request object. In the meantime, one workaround for this is to front end the application with a reverse proxy that adds the “x-forwarded-proto” header to requests. Requests received over HTTPS will then have the header x-forwarded-proto=https. This technique is used in HttpsAction.

In the development scenario, it is desirable to reproduce the redirect behavior, but without using a reverse proxy. In this case, a non-standard port for HTTPS, such as 9100, can be used. So, when running in development mode, HttpsAction checks the port number of the request rather than the x-forwarded-proto header to determine if a redirect is required.

Figure 2:  HttpsAction  class

There are a number of different ways to involve a reverse proxy and have the x-forwarded-protocol header added to inbound requests.  A practical example is an Amazon Elastic Load Balancer (ELB) which will add the header.  So, if you are running your application on an EC2 instance, using ELB is a very convenient solution.  This will work even if you are operating within the AWS free usage tier with a single instance, not requiring actual load balancing.  To use this approach, follow the AWS documentation to create an ELB and assign the EC2 instance where your Play application resides.

ReverseProxyELB
Figure 3: Logical Diagram of Production Environment

Configure HTTP and HTTPS listeners on the ELB as shown below.  You will need an SSL certificate in order to configure the HTTPS listener.

EC2 ELB Listener Configuration

Figure 4:  Configuration of the Amazon Elastic Load Balancer

The end result is a site that provides https protection to a subset of sensitive pages, while allowing http access to the rest.

References:

Leave a Reply

You must be logged in to post a comment.