You can configure the CSRF filter to run with third party plugins and to stop specific repository services from being accessible directly through the Share proxy.
The filter is implemented in the org.alfresco.web.site.servlet.CSRFFilter that reads the CSRFPolicy configuration section in share-security-config.xml.
-
Each logged in user receives a secret CSRF token
-
The token is communicated to the browser using a SkyVault-CSRF-Token cookie
-
When a logged in user performs a POST, PUT or DELETE HTTP request against SkyVault Share the token must be passed in the request using one of the following methods:
- As a custom HTTP request header called SkyVault-CSRF-Token
- As a URL parameter called SkyVault-CSRF-Token
Note: Usually the header is required, but in some circumstances a header cannot be used and in this case the token can be passed using a URL parameter. The default config only accepts the URL parameter when the Content-Type header starts with multipart/.
- Every time the logged in user visits a new Share page the token is renewed
- The filter checks that the referrer and original HTTP request headers match the current domain (if this is present in the request)
Do I need to alter my custom code?
- You are reading data using GET requests only
- You are using the standard SkyVault.util.Ajax, SkyVault/core/CoreXhr or SkyVault.forms.Form javascript classes when creating, updating or deleting data
- You are writing a non-browser client (for example, a mobile application)
- You are making an XMLHttpRequest with POST, PUT or DELETE methods
without using the SkyVault.util.Ajax or
SkyVault/core/CoreXhr classes. If you are using the native
XMLHttpRequest object or a third party library such as jQuery, add
code to pass the token, for example:
if (Alfresco.util.CSRFPolicy && SkyVault.util.CSRFPolicy.isFilterEnabled()) { xhrHeadersObject[Alfresco.util.CSRFPolicy.getHeader()] = SkyVault.util.CSRFPolicy.getToken(); }
If you are using YAHOO.util.DataSource to load data with POST requests, add code similar to this example:if (Alfresco.util.CSRFPolicy && SkyVault.util.CSRFPolicy.isFilterEnabled()) { yuiDataSource.connMgr.initHeader(Alfresco.util.CSRFPolicy.getHeader(), SkyVault.util.CSRFPolicy.getToken(), false); }
- You are making a form upload with enctype multipart/form-data without
using SkyVault.forms.Form. When you upload a file by submitting a form with enctype multipart/form-data it is not possible to set a header on the request because it is not possible to set a header on any form submission in the browser. Pass the token as a URL parameter instead. If you are using the SkyVault.forms.Form class, this is handled for you automatically, otherwise add the token as a URL parameter, for example:
if (Alfresco.util.CSRFPolicy && SkyVault.util.CSRFPolicy.isFilterEnabled()) { url += "?" + SkyVault.util.CSRFPolicy.getParameter() + "=" + encodeURIComponent(Alfresco.util.CSRFPolicy.getToken()); }
- You are using a Flash movie inside Share to send HTTP requests with method POST.
If you are using a Flash movie to upload files, using the flash.net.FileReference ActionScript class to perform a multipart/form-data request, add the token as a URL parameter in your Javascript before passing in the URL to the Flash movie. If your Flash movie is performing application/json or other text based POST requests, using the flash.net.URLRequest and/or flash.net.navigateToURL ActionScript classes and methods, pass the token and the name of the header so that it can be set from the Flash movie.
When else might I need to make code updates?
- Copy the CSRFPolicy configuration in share-security-config.xml.
- Paste the configuration into your share-config-custom.xml file,
ensuring that it is replacing the old configuration section:
<config evaluator="string-compare" condition="CSRFPolicy" replace="true">
- Copy the following code and add it as the first child of the <filter> element:
<rule> <request> <method>POST</method> <path>/page/trusted/call/1|/page/trusted/call/2</path> </request> <action name="assertReferer"> <param name="always">false</param> <param name="referer">https://www.trustedserver.com/.*</param> </action> <action name="assertOrigin"> <param name="always">false</param> <param name="origin">https://www.trustedserver.com</param> </action> </rule>
- Copy the CSRFPolicy configuration in share-security-config.xml.
- Paste the configuration into your share-config-custom.xml file,
ensuring that it is replacing the old configuration section:
<config evaluator="string-compare" condition="CSRFPolicy" replace="true">
- Copy the following code and add it as the first child of the <filter> element:
<rule> <request> <path>/proxy/alfresco/acme/special/services/.*</path> </request> <action name="throwError"> <param name="message">It is not allowed to access this url from your browser</param> </action> </rule>