Enabling CORS and file deletion issues

LabKey Support Forum
Enabling CORS and file deletion issues inaki martinez  2020-06-24 08:35
Status: Active
 

Dear Labkey community

we are having some issues while enabling CORS in labkey for some external collaborators. Our labkey instances work fine without CORS but as soon as we enable it, some labkey functionality does not work. As far as we could test, only file deletion stops working, but still is a problem.

Our labkey server has the following versions:

  • apache-tomcat: 8.5.53
  • openjdk:13.0.2
  • LabKey19.3.10-65330.20

The CORS configuration is as follows, although I've tried using just the default values without any luck.

      <filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>

        <init-param>
          <param-name>cors.allowed.origins</param-name>
          <param-value>https://bc2-labkey-dev.bc2.unibas.ch, https://bc2-labkey-dev.bc2.unibas.ch, https://labkey-dev.scicore.unibas.ch, https://labkey-dev.scicore.unibas.ch, https://wiki.biozentrum.unibas.ch, https://labkey.scicore.unibas.ch</param-value>
        </init-param>

        <init-param>
          <param-name>cors.allowed.methods</param-name>
          <param-value>GET,POST,OPTIONS</param-value>
        </init-param>

        <init-param>
           <param-name>cors.allowed.headers</param-name>
           <param-value>Access-Control-Expose-Headers,Access-Control-Allow-Origin,X-Requested-With,Content-type,Authorization</param-value>
        </init-param>

        <init-param>
          <param-name>cors.exposed.headers</param-name>
          <param-value>Access-Control-Expose-Headers,Access-Control-Allow-Origin,X-Requested-With,Content-type,Authorization</param-value>
        </init-param>

        <init-param>
          <param-name>cors.support.credentials</param-name>
          <param-value>true</param-value>
        </init-param>

        <init-param>
          <param-name>cors.preflight.maxage</param-name>
          <param-value>1800</param-value>
        </init-param>
      </filter>

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

Even with a simpler CORS setup it does not work:

      <filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>

        <init-param>
          <param-name>cors.allowed.origins</param-name>
          <param-value>*</param-value>
        </init-param>

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

Upon trying to delete a file I have just uploaded in the files tab, I get "Failed to delete" message. Firefox devel tools show:

Request URL:https://bc2-labkey-dev.bc2.unibas.ch/labkey/_webdav/home/%40files/afile_to_delete.txt?method=DELETE&pageId=4267287a-97a1-1038-bf7a-3c9cbf81b968
Request Method:POST
Remote Address:0.0.0.0:443
Status Code:
403
Version:HTTP/1.1
Referrer Policy:origin-when-cross-origin

The logs don't show any error during this request.

Is there anything else we should modify, or add for this to work? I'm currently out of ideas.

Best regards,
Iñaki

 
 
Matthew Bellew responded:  2020-06-25 10:10

I don't know much about CORS, but WebDav uses a lot of methods in addition to GET, POST, and OPTIONS. In addition, it uses: DELETE, PUT, COPY, LOCK, MKCOL, MOVE, PROPFIND, PROPPATCH, and UNLOCK. Perhaps those need to be added to the "cors.allowed.methods" section.

I see that the request above uses POST, however, so the other idea is permissions or CSRF checking.

 
inaki martinez responded:  2020-06-26 02:08

There is one detail that is confusing to me, as the issue does not happen if CORS is disabled, I can upload and delete files without trouble. So if I'm not explicitly enabling any CSRF filter, how is that is enforced/applied with the CORS filter? (I think you are right that having POST allowed, it must be something else).

I looked at the request headers to see I there was something missing and found X-LABKEY-CSRF, but adding it to the cors.allowed.headers does not change things

 
Matthew Bellew responded:  2020-06-26 10:48

Perhaps you have to add "Cookie" to the allowed headers, so the session is recognized for authentication? I will try to set this up locally to test as well.

 
Matthew Bellew responded:  2020-06-26 13:02

I got this to work, but CorsFilter is picky!

  1. Content-Type can not be blank. Setting it to "application/x-www-form-urlencoded" works.
  2. Using API keys to log in did work (still playing with regular Cookie/JSESSION authentication)
  3. For other developers trying to repro, you need to include the non default ports in the CORS config e.g. http://localhost:8080

xhr.open('POST', 'http://lk:8080/labkey/_webdav/home/%40files/1.jpg?method=DELETE');
xhr.setRequestHeader("Authorization", "Basic " + btoa('apikey:apikey|6a79d45d50b400eb787abbeb67838854'));
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = someHandler;
xhr.send();

 
Matthew Bellew responded:  2020-06-26 13:38

And you have to specify xhr.withCredentials to send cookies. So this works if the user is logged in to the 'remote' web server. I don't know if all browsers support this.

xhr.open('POST', 'http://lk:8080/labkey/_webdav/home/%40files/2.jpg?method=DELETE');
xhr.withCredentials = true;
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = someHandler;
xhr.send();

 
inaki martinez responded:  2020-06-26 15:49

I have tried adding the cookie header and other headers shown by Chrome, but none make it work.

The methods you describe should be added to the web.xml configuration file or is something that has to be done at the application level?

 
Matthew Bellew responded:  2020-06-26 16:07
Status: Closed

The changes were required in the browser Javascript code. I had to explicitly set the "Content-Type" header and the withCredentials flag on the XMLHttpRequest object.