Category Archives: Java

How to debug CORS requests with Firebug

CORS FilterFirebug, the indispensable Firefox add-on for serious developers, is great for debugging web apps that make use of the new CORS mechanism for cross-domain requests. The acronym CORS stands for Cross-Origin Resource Sharing and was developed by a group of web activists to address the issue of making browser cross-domain requests in a standards-compliant way. The goal is to make CORS an official W3C standard. As of 2010 most browsers such as FF, IE, Chrome and Safari support it.

My first encounter with CORS was during the development of Json2Ldap, a smart piece of software designed to turn one or more LDAP directories into a web friendly JSON-RPC service. Json2Ldap turned out to be an excellent case for CORS as the web service had to be capable of serving cross-domain requests. Later I span off the server-side CORS code into a project on its own, called CORS Filter. It provides a generic servlet filter which can be retrofitted to any existing Java web app to make it cross-domain XHR capable.

Firebug has an excellent network activity monitor which can be used to reveal the CORS-specific conversation between browser and server during a cross-domain XHR. This is great for understanding how the protocol works, particularly the behaviour of simple/actual vs. pre-flight CORS requests.

To observe a CORS request in action you need a relatively recent version of Firebug (e.g. 1.6). Click on the “Net” tab and then on the “XHR” tab, then launch your cross-domain request.

How to load the Firebug Network Monitor

For a simple/actual CORS request Firebug will then display the following headers:

Simple/actual CORS request

Note the Origin header which the browser inserted to identify the domain from which the HTML page originated. The server checks the Origin value and responds accordingly, by either allowing or denying the request.

Simple CORS response

If the server allowed the origin it replies with an Access-Control-Allow-Origin header that contains a verbatim copy of the Origin header value or * (meaning any origin). The server may also include optional CORS response headers, such as Access-Control-Allow-Credentials (to tell the browser that it accepts cookies) or Access-Control-Expose-Headers (to tell the browser which custom headers are safe to expose to the requesting script).

CORS also has the so-called preflight request which browsers can send using HTTP OPTIONS prior to the actual CORS request to query the CORS settings of a particular HTTP server, such as the supported HTTP methods, custom headers, etc.

Tip: How to simulate a cross-domain request if you have just a single HTTP server to play with: Create a host alias of your web server and reload the requesting page using the alias URL.

Finally, today I learned that the Jetty 7 web server has a CORS filter implementation similar to the one I developed few months ago. On first inspection the only notable difference is that it doesn’t support request tagging and the Access-Control-Expose-Headers response header.

Json2Ldap 1.6

Json2Ldap iconOctober saw a release of Json2Ldap version 1.6 which brings updates in three areas: the web API, addition of CORS support and library upgrades. The software is now being put to serious use and I’m glad to see its popularity pick up, despite having no dedicated marketing effort behind it. I must say the whole concept of web-enabling LDAP directories with a simple JSON-RPC API is one very attractive proposition for companies offering web services, such as social networking or SaaS, as a way to provide web-exposed user storage API and authentication in a standard and web friendly fashion.

Cross-Origin Resource Sharing (CORS)

Json2Ldap now includes support for the CORS protocol that allows browsers to make cross-origin XHR requests, in the spirit of modern Ajax/Web 2.0 applications where a web application uses data and methods from several sources. CORS is now supported by most mainstream browsers, such as Firefox, IE, Chrome and Safari. The protocol is implemented by a highly flexible and configurable servlet filter, which I also offer as a separate add-on product to customers who want to add CORS to their own Java web services.

Json2LDAP API changes

Json2Ldap 1.6 also makes some minor changes to the web API, in order to make it more generic and allow for future implementation of LDAP extensions, such as password expiration controls.

  • Connection identifiers (CIDs), returned by the ldap.connect call, are now represented by standard GUIDs (or UUIDs).
  • ldap.connect returns an object where the CID values is put into a separate field.
  • ldap.simpleBind and ldap.anonymousBind return empty object instead of null; this is to allow for new optional result fields in future without breaking backward compatibility.

Configuration

New configuration parameter json2ldap.clients.responseContentType which sets the MIME type of Json2Ldap responses.

Library upgrades

Many of the underlying libraries were also upgraded to recent stable versions:

  • UnboundID SDK JAR to 1.1.6.
  • JsonRpc2-Base JAR to 1.11.
  • JsonRpc2-Proc JAR to 1.1.
  • Property Util to 1.2.

Also, the JSON-RPC 2.0 Shell tool was upgraded to version 1.4.

Roadmap

What’s ahead? For version 1.7 I plan to add support for the simple page results control (RFC 2696). I also consider implementing the SASL external bind control, as defined in RFC 4422.

ForgeRock forks OpenDS to create OpenDJ

Last week I learned that ForgeRock, a fresh company formed by people from Sun’s directory + IdM business who decided to leave after Oracle’s takeover (no surprise here, I suppose), has forked Sun’s open source Java directory OpenDS to start a new project under the name OpenDJ. Perhaps not coincidentally, Mr. Ludovic Poitou, until recently the project lead for OpenDS, has also moved to ForgeRock, assuming the role of a product manager for OpenDJ.

Previously, ForgeRock forked Sun’s OpenSSO to create OpenAM.

As a user of OpenDS (my preferred back-end for my in-house Json2Ldap gateway/proxy applications) I’ll be paying close attention at OpenDJ’s further development at ForgeRock. In my opinion, OpenDS is one very good piece of LDAP software and OpenDJ has the potential to become an even greater success.

OpenDJ, by the way (despite the musical connotation, I suppose the “D” stands for directory and the “J” for Java), is not the first major fork of OpenDS. A similar thing has happened before with several other directory guys from Sun who had left to found UnboundID. The US company offers its own directory derived from OpenDS code (as well as the neat UnboundID LDAP Java SDK, which I use in Json2Ldap).

The moral of this story? Open source (and ideas in general) move to better places if they have to.

Escaping special chars in LDAP search filters

Json2Ldap iconWhen programming against the Json2Ldap web API (or for that matter, against any LDAP backend) it’s good to sanitise any user input that may go into a search filter. A typical case is authentication (login or single sing-on) applications, where an input username or email must be used to resolve a user’s distinct name (DN) in the LDAP directory.

Consider for example the following search filter template, which is used to get a user based on finding an exact match of their uid or mail attribute.

(|(uid=%u)(mail=%u))

The %u placeholder is replaced by the user input and the resulting string is used to create the LDAP search filter. If the user enters john@example.com into the login form the resulting search filter string would become this:

(|(uid=john@example.com)(mail=john@example.com))

If, however, the user enters *, this will trigger a match-any search, since this is what the asterisk means in the context of LDAP search filters.

(|(uid=*)(mail=*))

To prevent this from happening you may limit the range of acceptable input characters or you may use a function that sanitises the input by escaping all special characters in the assertion value. The special search filter characters and how to escape them is specified in detail in RFC 4515 (LDAP: String Representation of Search Filters).

Here is one such sanitising method, written in Java:

/**
 * Escapes any special chars (RFC 4515) from a string representing a
 * a search filter assertion value.
 *
 * @param input The input string.
 *
 * @return A assertion value string ready for insertion into a 
 *         search filter string.
 */
public static String sanitize(final String input) {

        String s = "";

        for (int i=0; i< input.length(); i++) {

                char c = input.charAt(i);

                if (c == '*') {
                        // escape asterisk
                        s += "\\2a";
                }
                else if (c == '(') {
                        // escape left parenthesis
                        s += "\\28";
                }
                else if (c == ')') {
                        // escape right parenthesis
                        s += "\\29";
                }
                else if (c == '\\') {
                        // escape backslash
                        s += "\\5c";
                }
                else if (c == '\u0000') {
                        // escape NULL char
                        s += "\\00";
                }
                else if (c <= 0x7f) {
                        // regular 1-byte UTF-8 char
                        s += String.valueOf(c);
                }
                else if (c >= 0x080) { 

                        // higher-order 2, 3 and 4-byte UTF-8 chars

                        try {
                                byte[] utf8bytes = String.valueOf(c).getBytes("UTF8");

                                for (byte b: utf8bytes)
                                        s += String.format("\\%02x", b);

                        } catch (UnsupportedEncodingException e) {
                                // ignore
                        }
                }
        }

        return s;
}

If there is sufficient demand, I will consider including such a sanitising method to the web API of Json2Ldap.