Thursday, September 18, 2014

How to enforce secured connections with IBM Bluemix?

IBM Bluemix has a DataPower appliance in front of all deployed application (see Bluemix security). In particular, the DataPower terminates secured connections so that secured connections are forwarded to the application using non-secured connections. For example all the HTTPS traffic is forwarded as HTTP traffic to your applications.

This is very nice because you have nothing to configure in your app to accept secured connections. In addition, all the compute power needed to decrypt messages is on the DataPower, and not your application server instance.

However, it has one very important drawback. It does not enforce the use of secured connections. For example, a client application could use HTTP where HTTPS should have been used. This would be a major issue when using Basic Authentication, or anytime an Authorization header or access token is used.

Fortunately the DataPower sets some interesting headers to indicate several attributes of the original connection. One of them is the header $WSIS that indicates if the original connection was secured or not. With this in mind, we can easily write a servlet filter like this:


  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
    if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
      HttpServletRequest req = (HttpServletRequest)request;
      HttpServletResponse res = (HttpServletResponse)response;
      String wsis = req.getHeader("$wsis");
      if (wsis!=null && !wsis.equalsIgnoreCase("true")){
        res.setStatus(403);
        return;
      }
    }
    chain.doFilter(request, response); 
  }
With this filter, 403 (FORBIDDEN) is returned if non-secured connections were used, so that secured connections are enforced when deployed to Bluemix. In addition, when you test your application locally you can still use the non-secured connections because the header $WSIS will not be present.

To conclude, I recommend to use this simple filter.

1 comment:

  1. ServletRequest#isSecure() is simpler, and WAS uses $WSIS under the covers.

    ReplyDelete