Thursday, May 31, 2012

Build secure, cross-origin resource sharing RESTful web services using Jersey, CORS filter, and OAuth

Overview

My company is taking on the challeng of building out next generation platform based on secure RESTful web services, which must be secured through OAuth and support Cross-Origin Resource Sharing (CORS).

Web Services can be implemented as SOAP and WSDL based or RESTful based. Our new platform will be implemented as RESTful based web service.

Our new platform also needs to support Cross Origin Resource Sharing, which allows third party Javascript to call our platform without being restricted to the same domain. Traditionally the browser enfoces that an AJAX can only call back to the same domain. For CORS supported browser, however, the browser can grant cross domain access if proper access is returned by the back end web services.

Our platform must be secure. After some initial investigation, we decided to go with OAuth2, the next generation of OAuth protocol. The OAuth protocol enables websites or applications (Consumers) to access Protected Resources from a web service (Service Provider) via an API, without requiring Users to disclose their Service Provider credentials to the Consumers. More generally, OAuth creates a freely-implementable and generic methodology for API authentication.

After some research and prototyping, we settle on the following set of technologies to address our particular challenges;
  • Use Jersey to implement RESTful web services
  • Use CORS filter to implement CORS support
  • Implement and deploy on Tomcat OAuth valve class for OAuth support
In this blog series, we will illustrate the following,

RESTful Web Services Framework

The initial candidates consist of three JAX-RS compliant RESTful Web Services framework,


RESTful Framework Description Experience
Jersey Jersey is the JAX-RS reference
implementation from Oralce. One
chooses between CDDL 1.1 license
or GPL 2 with CPE license
Easy to develop and configure.
Has good JSON support.
No external dependency, although
does offer Spring integration
JBoss RESTeasy RESTeasy is maintained by Jobs
and uses Apache 2.0 license
Easy to develop with a lot of
JBoss dependencies
Apache CXF Apache CXF offers both WSDL-based
and RESTful web services and uses
Apache 2.0 license
Easy to develop, heavy
framework with a lot of
dependencies and support for
JAX-WS

We prototyped in all three frameworks and they are all relatively easy to develop and configure. We decided to go with Jersey for the following reasons,

  • Reference implementation
  • Small set of libraries
  • No external dependency
  • Can easily switch if Jersey does not meet our needs in the future

Migrate to another framework

Since all three frameworks are JAX-RS compliant, the implementation classes use JAX-RS standard annotation and there is no direct dependency on the framework. If we need to swamp out Jersey with another framework, we just need to configure Tomcat web application's web.xml with framework specific configuration and deploy framework specific libraries to the lib directory.

CORS Support

We prototyped CORS support based on the following frameworks, CXF CORS support and CORS filter. We couldn't get CXF CORS to even compile, as the class structure has changed from the sample code. Once we fixed the compilation issue, we still couldn't get CORS to work through AJAX.

CORS filter, on the other hand, was a pleasure to work with. In a span of half a day, we quickly set up and integrated CORS filter with Jersey, RESTeasy, and CXF. The only drawback about CORS filter is that it is not as flexible as CXF CORS because CORS filter can only be configured at the global level, while CXF CORS can be configured at each class level, if one can get CXF CORS to work.

So, I decide to go with CORS filter as the one and only working solution.

OAuth Support

All our RESTful web services must be secured with OAuth support. There are potentially a few options on how to implement this and in the end we decided to implement this a Tomcat Valve instead of using a security realm or a servlet filter. The big advantage of implementing OAuth as a Valve is the flexibility of deploying the Valve at the Host level or at the web application level, while servlet filter can only be deployed at the web application level. More on this topic in a later blog.