Giovanni Domenico Tipeolo, Procession of the Trojan Horse in Troy (1773)Alfresco Enterprise 4.1.4 was released on Thursday, bringing with it a slew of security and stability fixes. One such fix protects against cross-site request forgeries (CSRF). A CSRF attack is one in which malicious code pretends to be an authenticated user by piggy-backing on the trust granted to the user's browser, then performing requests as that user.

If you've built a custom application based on the Alfresco platform and are performing POST requests against either Share- or repository-tier webscripts, you may encounter problems after upgrading to 4.1.4 due to this fix. In this post, I will explain how to update your application to work with this fix.

Edit: Here is an official blog post on the new CSRFPolicy.

I first ran into trouble when I upgraded a client's test server to the 4.1.4 release. The custom web application I had built for them was no longer able to submit requests to Alfresco. Specifically, POST requests started returning a 500 Internal Server Error and when I turned on the appropriate debug filter in Tomcat, I noticed the following:

DEBUG [site.servlet.CSRFFilter] [http-8080-1] Assert token POST /your/webscript/url :: session: 'AL7SDyCLJnfiWu/DoSmlL48tg9XYnGYSjn84bnLBb+E=' vs header: 'null' INFO [site.servlet.CSRFFilter] [http-8080-1] Possible CSRF attack noted when comparing token in session and request header. Request: POST /your/webscript/url org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet default threw exception javax.servlet.ServletException: Possible CSRF attack noted when comparing token in session and request header. Request: POST /your/webscript/url at org.alfresco.web.site.servlet.CSRFFilter$AssertTokenAction.run(CSRFFilter.java:626) at org.alfresco.web.site.servlet.CSRFFilter.doFilter(CSRFFilter.java:290) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.alfresco.web.site.servlet.SSOAuthenticationFilter.doFilter(SSOAuthenticationFilter.java:374) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:680) ERROR [alfresco.web.site] [http-8080-1] javax.servlet.ServletException: Possible CSRF attack noted when comparing token in session and request header. Request: POST /your/webscript/url

A little investigation revealed the CSRF patch -- generously contributed by the fine folks at UC Berkeley -- as the culprit. To work with the patch, I would have to prove to Alfresco that the requests coming from my application were legitimate.

This is actually really easy to do if your web application is integrated with Alfresco Share. In my case, not only is my application embedded in Share as an additional Surf page, I'm also pulling in the "alfresco.js" utility file, which now includes the "Alfresco.util.CSRFPolicy" helper object. This object has a getToken() function which returns the current user's CSRF token. The token is a string value that tells Alfresco the request is legitmate when supplied as the "Alfresco-CSRFToken" parameter in your POST request header.

If your application uses jQuery, this is even easier, as you can bind a listener to the global ajaxSend event:

var csrf_token = Alfresco.util.CSRFPolicy.getToken(); if (csrf_token) { $("body").bind("ajaxSend", function(elm, xhr, s){ if (s.type == "POST") { xhr.setRequestHeader('Alfresco-CSRFToken', csrf_token); } }); }

This ensures the CSRF token is supplied in the header of every POST request your application makes.


Loading Conversation