Last updated Apr 2, 2024

Enable XSRF protection in your app

AvailabilityConfluence 3.0 or later

This page demonstrates how to protect your app’s Struts actions and servlets from cross-site request forgery (XSRF) attacks (also known as CSRF attacks).

An XSRF token is a unique, secret, unpredictable value that is generated by the server-side application and transmitted to the client in such a way that it’s included in a subsequent HTTP request made by the client.

XSRF protection is an opt-out feature (opt-in prior to Confluence 9.0) for Struts Actions, and opt-in for servlets.

Configure Struts actions

Configure accepted request methods

Actions, by default, will only accept POST requests, EXCEPT for Actions which map to a method named doDefault which will accept GET or POST. We strongly recommend restricting your Actions to accept only its required request methods. Ordinarily, any request which mutates application state (e.g. handling a form submission) should NOT accept GET (or HEAD, OPTIONS, TRACE) requests. It also follows that any request which mutates application state should require an XSRF token.

The accepted request methods for an Action can be configured in 2 ways. In both cases you must ensure your Action package defines or inherits the validatingStack interceptor stack (<interceptor-ref name="validatingStack"/>).

Annotation approach

Locate the Java method which an Action maps to and add the following annotation, specifying the desired request methods:

1
2
@com.atlassian.xwork.PermittedMethods({HttpMethod.GET, HttpMethod.TRACE})

XML approach

Locate the Action definition in atlassian-plugins.xml and add the following child element, specifying the desired request methods:

1
2
<param name="permittedMethods">GET,TRACE</param>

Configure XSRF token requirement

All requests made to Struts Actions which are not GET (or HEAD, OPTIONS, TRACE) requests will require a token unless explicitly opted out. All GET (or HEAD, OPTIONS, TRACE) requests will not require a token unless explicitly opted in. Ideally, your app will not have any Actions that accept these safe request methods and mutate application state, and so explicitly opting in should be rarely required.

A Struts action can be configured to require or not require a token in 2 ways.

Annotation approach

Locate the Java method which an Action maps to and add the following annotations.

To opt-out (for non-GET requests):

1
2
@com.atlassian.annotations.security.XsrfProtectionExcluded

To opt-in (for GET requests):

1
2
@com.atlassian.xwork.RequireSecurityToken(true)

XML approach

Locate the Action definition in atlassian-plugins.xml and add the following child element.

To opt-out (for non-GET requests):

1
2
<param name="RequireSecurityToken">false</param>

To opt-in (for GET requests):

1
2
<param name="RequireSecurityToken">true</param>

Examples

Here are examples of a Struts Action which accepts both GET and POST requests and does not require a token:

Java

1
2
@XsrfProtectionExcluded
@PermittedMethods({HttpMethod.GET, HttpMethod.POST})
public String execute() throws Exception {
    return SUCCESS;
}

XML

1
2
<action name="index" class="com.atlassian.confluence.core.ConfluenceActionSupport">
    <param name="RequireSecurityToken">false</param>
    <param name="permittedMethods">GET,POST</param>
    <result name="success" type="dispatcher">/admin/console.action</result>
</action>

Configure servlets

To enable servlet XSRF protection add an init parameter in atlassian-plugin.xml under the servlet tag:

1
2
<init-param>
   <param-name>RequireSecurityToken</param-name>
   <param-value>true</param-value>
</init-param>

Example

Here’s an example atlassian-plugin.xml file containing a single servlet with XSRF protection enabled:

1
2
<atlassian-plugin name="Hello World Servlet" key="example.plugin.helloworld" plugins-version="2">
    <plugin-info>
        <description>A basic Servlet module test - says "Hello World!</description>
        <vendor name="Atlassian Software Systems" url="http://www.atlassian.com"/>
        <version>1.0</version>
    </plugin-info>

    <servlet name="Hello World Servlet" key="helloWorld" class="com.example.myplugins.helloworld.HelloWorldServlet">
        <description>Says Hello World, Australia or your name.</description>
        <url-pattern>/helloworld</url-pattern>
        <init-param>
            <param-name>RequireSecurityToken</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
</atlassian-plugin>

Provide the token

The way you provide the token depends on how the request is made.

Safe methods must be idempotent

In order for either the Struts action or servlet XSRF protection to work, apps must ensure that "safe" HTTP methods are idempotent. This means that requests with the HTTP method GET, HEAD, OPTIONS, and TRACE should not change the state of the application.

Provide the token in HTML Forms

The Velocity macro #form_xsrfToken() will insert the following into your form:

1
2
<input type="hidden" name="atl_token" value="[the user's token]">

Provide the token in AJAX calls

The Atlassian Javascript Library (AJS) contains a method that will add the security token to an AJAX callback. To make this method available, place the following call in your Velocity template:

1
2
#requireResource("confluence.web.resources:safe-ajax")

This library provides wrappers around JQuery AJAX functions that will include the form token in the AJAX submission. If you’re not using the JQuery AJAX functions, you should first update your code to use them directly, then use the safe version. The following functions are provided:

1
2
AJS.safe.ajax()
AJS.safe.post()

Provide the token in AJAX calls directly

To provide the token in AJAX calls directly:

1
2
AJS.Meta.get("atl-token")
Meta.get("atl-token")

Access the token programmatically

To get the current user's token, make the following call:

1
2
new com.atlassian.xwork.SimpleXsrfTokenGenerator().generateToken(httpServletRequest)

For the best long-term compatibility, you should retrieve the name of the form parameter to set from the token generator rather than using the literal string "atl_token". For example:

1
2
HttpServletRequest req = ServletActionContext.getRequest();
if (req != null)
{
    XsrfTokenGenerator tokenGenerator = new SimpleXsrfTokenGenerator();
    myWebRequest.addParameter(tokenGenerator.getXsrfTokenName(), tokenGenerator.generateToken(req))
    // or: myRequestUrl.append("&" + tokenGenerator.getXsrfTokenName() + "=" + tokenGenerator.generateToken(req));
}
else
{
    // We are not in a web context. Handle this error cleanly.
}

Bypass token check in scripts

Scripts used to access Confluence remotely may have trouble acquiring or returning a security token or maintaining an HTTP session with the server. To opt-out of token checking, include the following HTTP header in the request:

1
2
X-Atlassian-Token: no-check

Rate this page: