CORS, AJAX, the Bonita Rest AP, and Tomcat7

Has anyone had success making a cross origin call to the Bonira REST API running under Tomcat 7?

We have setup Bonita Subscription 6.2.3 instance on an Amazon EC2 server.  The portal is working; however, we are unable to invoke any Cross Origin REST calls that requre a preflight request.  In every case we get a 401 error.  The chrome console shows the following messages:

OPTIONS http://myserver.company.com:8080/bonita/API/bpm/humanTask?p=0&c=10&f=state=ready 401 (Unauthorized) jquery-1.11.0.js:9666
OPTIONS http://myserver.company.com:8080/bonita/API/bpm/humanTask?p=0&c=10&f=state=ready No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8082' is therefore not allowed access. jquery-1.11.0.js:9666
XMLHttpRequest cannot load http://myserver.company.com:8080/bonita/API/bpm/humanTask?p=0&c=10&f=state=ready. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8082' is therefore not allowed access.

The problem can be demonstrated with the following block of code:

// Log in to Bonita.
bonitaUrl = http://mysever.company.com:8080/bonita/
$.ajax({
    xhrFields: {withCredentials: true},
    contentType: "application/x-www-form-urlencoded",
    url: bonitaUrl + "loginservice",
    type: 'POST',
    data: 'username=walter.bates&password=bpm&redirect=false&redirectUrl= ', //redirectUrl is required as a workaround to a null pointer exception.
}).done(function(data, textStatus, request){
    $.ajax({
        xhrFields: {withCredentials: true},
        contentType: "application/json", //Comment this line and there is no preflight call.  Everything works in that case.
        url: bonitaUrl + "API/bpm/humanTask?p=0&c=10&f=state=ready",
        type: 'GET',
    }).done(function(data, textStatus) {
        for(var i = 0; i < data.length; i++) {
           $('#processes tbody').append('<tr><td><a href="javascript:void(0);" onclick="javascript:BonitaPOC.switchToWorkOrder(' +
           data[i]["caseId"] +');"</a>' + data[i]["caseId"] + '</td><td>'+ data[i]["displayName"] + '</td></tr>');
        }
        $.ajax({
            xhrFields: {withCredentials: true},
            url: bonitaUrl + "logoutservice?redirect=false",
            type: 'GET'
        });
    });
});

I know that the contentType: "application/json" call is not requred for a simple get request; however, it does force the code to make a preflight call which demonstrates the issue.  Any other call that requires a preflight call causes the same issue (i.e. a  "PUT" call).  If I remove the contentType setting for the humanTask call this code will work which tells me that there is a problem with the CORS filter; however, I simply don't see a problem with the setup.

Here are the request and response headers that are being generated:

Request Headers:
OPTIONS /bonita/API/bpm/humanTask?p=0&c=10&f=state=ready HTTP/1.1
Host: myserver@company.com:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:8082
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36
Access-Control-Request-Headers: accept, content-type
Accept: */*
Referer: http://localhost:8082/index.html?mode=order
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

Response:Headers:
Content-Length:0
Date:Mon, 17 Mar 2014 21:26:38 GMT
Server:Apache-Coyote/1.1
Set-Cookie:JSESSIONID=4712E4515783B0E76F34F835FE0FD5A3; Path=/bonita/; HttpOnly

I have activated CORS under /usr/share/tomcat7/conf/web.xml.  I have tried the native filter (org.apache.catalina.filters.CorsFilter) and a filter from com.thetransactioncompany.cors.CORSFilter, both libraries show identical behavior:

Here is my filter setup using thetransactioncompany cors filter:

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    
    <init-param>
      <param-name>cors.allowGenericHttpRequests</param-name>
      <param-value>true</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.allowOrigin</param-name>
      <param-value>*</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.allowSubdomains</param-name>
      <param-value>false</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.supportedMethods</param-name>
      <param-value>GET, HEAD, POST, PUT, OPTIONS</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.supportedHeaders</param-name>
      <param-value>*</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.exposedHeaders</param-name>
      <param-value>X-Test-1, X-Test-2</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.supportsCredentials</param-name>
      <param-value>true</param-value>
    </init-param>
    
    <init-param>
      <param-name>cors.maxAge</param-name>
      <param-value>3600</param-value>
    </init-param>
  </filter>

  <filter-mapping>
          <filter-name>CORS</filter-name>
          <url-pattern>/*</url-pattern>
  </filter-mapping>

The strange thing is that these cross origin calls work well if point the at my development instance (Community Edition 6.2.3), which of course runs a bundled version of Tomcat.  I simply cannot get a call that causes a preflight call to work on the Amazon instance under Tomcat 7.

 

1 Like

A solution to this was found.  I am posting it here in the hopes that it will help someone else in the future.

We commented out the valve element with classname "org.bonitasoft.console.security.SessionFixationValve" in /usr/share/tomcat7/conf/server.xml.

Once that was done and tomcat was restarted our cross origin calls started working.

From what I understand this entry is in place to help prevent session fixation attacks.  It seems to also reject any CORS preflight call in our experience when running the Bonita BPM deployment bundle regardless of the version of tomcat (6 or 7).

When running the BonitaBPM for Mac code locally and starting the portal (invoking the version of Tomcat that comes with the studio code) the issue was not observed even though the same SessionFixationValve entry exists in the server.xml file present in the bundled version of Tomcat.

I found that with BonitaBPM 7.0.2, I also had to add the following to the web.xml in /webapps/bonita/WEB-INF/

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

I can confirm that adding the above fragment is needed as well (I am using BonitaBPM 7.2.3)

in fact placing the filter and filter-mapping as per the above is the ONLY thing needed!