2

I've created a module extension to use with Alfresco 5 Community Edition. Everything works great, I have my .get methods taken care of and they display properly.

On the page I have a button which posts back to the server to display a result (right now it's empty for testing). When I click the button I get a server error:

javax.servlet.ServletException: Possible CSRF attack noted when comparing token in session and request header. Request: POST /share/service/components/console/reset-dashboards
    at org.alfresco.web.site.servlet.CSRFFilter$AssertTokenAction.run(CSRFFilter.java:827)
    at org.alfresco.web.site.servlet.CSRFFilter.doFilter(CSRFFilter.java:312)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2466)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2455)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

Checking the webscripts uri at http://localhost:8080/share/page/index/uri/components/console/reset-dashboards I can see everything is registered properly

Reset Dashboards
GET /share/page/components/console/reset-dashboards
Description:    Dashboard Tools - Reset All Dashboards To Default
Authentication: none
Transaction:    none
Format Style:   any
Default Format: html
Id: com/company/components/console/dashboard-tools/reset-dashboards.get
Description:    classpath:alfresco/site-webscripts/com/company/components/console/dashboard-tools/reset-dashboards.get.desc.xml

Reset Dashboards POST
POST /share/page/components/console/reset-dashboards
Description:    Dashboard Tools - Reset All Dashboards To Default POST
Authentication: user
Transaction:    required
Format Style:   any
Default Format: json
Id: com/company/components/console/dashboard-tools/reset-dashboards.post
Description:    classpath:alfresco/site-webscripts/com/company/components/console/dashboard-tools/reset-dashboards.post.desc.xml

This is the information for the GET webscript:

Script Properties
Id: com/company/components/console/dashboard-tools/reset-dashboards.get
Short Name: Reset Dashboards
Description:    Dashboard Tools - Reset All Dashboards To Default
Authentication: none
Transaction:    none
Method: GET
URL Template:   /components/console/reset-dashboards
Format Style:   any
Default Format: html
Negotiated Formats: [undefined]
Implementation: class org.springframework.extensions.webscripts.DeclarativeWebScript
Extensions: [undefined]

Store: classpath:alfresco/site-webscripts

File: com/company/components/console/dashboard-tools/reset-dashboards.get.desc.xml

<webscript>
    <shortname>Reset Dashboards</shortname>
    <description>Dashboard Tools - Reset All Dashboards To Default</description>
    <url>/components/console/reset-dashboards</url>
    <family>admin-console</family>
</webscript>

File: com/company/components/console/dashboard-tools/reset-dashboards.get.html.ftl

<@markup id="css" >
<#-- CSS Dependencies -->
    <@link href="${url.context}/res/components/console/application.css" group="console"/>
</@>

<@markup id="js">
<#-- JavaScript Dependencies -->
    <@script src="${url.context}/res/components/console/consoletool.js" group="console"/>
    <#--<@script src="${url.context}/res/components/console/application.js" group="console"/>-->
</@>

<@markup id="widgets">
    <@createWidgets group="console"/>
</@>

<@markup id="html">
    <#assign el=args.htmlid?html>
    <form id="${el}-options-form" action="${url.context}/service/components/console/reset-dashboards" method="post">
        <div class="buttons">
            <button id="${el}-apply-button" name="apply">${msg("button.reset")}</button>
        </div>
    </form>
</@>

File: com/company/components/console/dashboard-tools/reset-dashboards.get.js

function main()
{
}

main();

Store: classpath:surf/webscripts

[No implementation files]

Store: classpath:webscripts

[No implementation files]

This is the information for the POST webscript:

Script Properties
Id: com/company/components/console/dashboard-tools/reset-dashboards.post
Short Name: Reset Dashboards POST
Description:    Dashboard Tools - Reset All Dashboards To Default POST
Authentication: user
Transaction:    required
Method: POST
URL Template:   /components/console/reset-dashboards
Format Style:   any
Default Format: json
Negotiated Formats: [undefined]
Implementation: class org.springframework.extensions.webscripts.DeclarativeWebScript
Extensions: [undefined]

Store: classpath:alfresco/site-webscripts

File: com/company/components/console/dashboard-tools/reset-dashboards.post.desc.xml

<webscript>
    <shortname>Reset Dashboards POST</shortname>
    <description>Dashboard Tools - Reset All Dashboards To Default POST</description>
    <format default="json" />
    <url>/components/console/reset-dashboards</url>
    <authentication>user</authentication>
</webscript>

File: com/company/components/console/dashboard-tools/reset-dashboards.post.json.ftl

{
    "success": ${success?string},
    "message": "<#if errormsg??>${errormsg}</#if>"
}

File: com/company/components/console/dashboard-tools/reset-dashboards.post.json.js

function main()
{
    model.success = true;
}

main();

Store: classpath:surf/webscripts

[No implementation files]

Store: classpath:webscripts

[No implementation files]

Again, when I click the button on the page to post to the webscript, it gives me a Possible CSRF attack exception. How do I correct this? Is it possible to do it inside the module extension jar file?

UPDATE

I did notice that all other scripts that post as part of Alfresco contain the Alfresco-CSRFToken header and a cookie of the same name. My script only contains Alfresco-CSRFToken as a cookie and is missing as a header. I'm not sure how to make sure this exists as a header though.

vane
  • 2,125
  • 1
  • 21
  • 40

1 Answers1

2

If you are calling repository webscripts in your alfresco share client side script then you need to take care of following points in order to pass CSRF filter.

Try to use standard Alfresco.util.Ajax, alfresco/core/CoreXhr or Alfresco.forms.Form while sending request.

If you are not using any of above then you need to put extra checks related to CSRF tokens as follow.

if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled())
{
   xhrHeadersObject[Alfresco.util.CSRFPolicy.getHeader()] = Alfresco.util.CSRFPolicy.getToken();
}

In case of YUI datasource.

   if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled())
{
   yuiDataSource.connMgr.initHeader(Alfresco.util.CSRFPolicy.getHeader(), Alfresco.util.CSRFPolicy.getToken(), false);
}

By using above methods you can get rid of CSRF attack related errors in your code.

mitpatoliya
  • 2,037
  • 12
  • 23
  • I saw this already and the thing about it is that everyone just says "it's simple, just add this snippet of javascript"... well, WHERE do you add that snippet of javascript? I've solved this on my own already and it required digging deep into the Alfresco code to determine what was happening and it involves creating a client side widget javascript file that wires your form up on load to properly submit. – vane Sep 02 '15 at 00:54
  • Yes, you need to create client side javascript from where you will be calling webscript and hence this code will go inside that. – mitpatoliya Sep 02 '15 at 05:19