Hello,

Just wanted to follow-up, as I was able to get this working with the following 
configuration:

My WebApplication class has a request cycle listener to set a csrf token as 
metadata:
```
...
public static final MetaDataKey<CsrfToken> CSRF_TOKEN_KEY = new MetaDataKey<>() 
{};
...
@Override
protected void init() {
        ...
        setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
        getRequestCycleListeners().add(new 
ResourceIsolationRequestCycleListener());
        getRequestCycleListeners().add(new IRequestCycleListener() {

            @Override
            public void onBeginRequest(RequestCycle cycle) {

                HttpServletRequest request = (HttpServletRequest) 
cycle.getRequest().getContainerRequest();
                CsrfToken token = (CsrfToken) 
request.getAttribute(CsrfToken.class.getName());

                if (token != null) {
                    cycle.setMetaData(CSRF_TOKEN_KEY, token);
                }

                IRequestCycleListener.super.onBeginRequest(cycle);
            }
        });
}
```

Then, my BasePage (extended by all pages) leverages this and sets to set the 
request header via Wicket.Event.subscribe:
```
    @Override
    public void renderHead(IHeaderResponse response) {
        super.renderHead(response);

        CsrfToken token = 
RequestCycle.get().getMetaData(CsurpsWebApplication.CSRF_TOKEN_KEY);

        if (token != null) {

            response.render(StringHeaderItem.forString(String.format("<meta 
name=\"_csrf\" content=\"%s\"/>", token.getToken())));
            response.render(StringHeaderItem.forString(String.format("<meta 
name=\"_csrf_header\" content=\"%s\"/>", token.getHeaderName())));

            response.render(JavaScriptHeaderItem.forReference(new 
PackageResourceReference(BasePage.class, "csrf.js")));
        }
    }
```

csrf.js:
```
(function() {
    var csrfToken = document.querySelector('meta[name="_csrf"]')?.content;
    var csrfHeader = 
document.querySelector('meta[name="_csrf_header"]')?.content;

    if (csrfToken && csrfHeader && window.Wicket && Wicket.Event && 
Wicket.Ajax) {
        Wicket.Event.subscribe('/ajax/call/beforeSend', function(jqEvent, 
attributes, jqXHR, settings) {
            jqXHR.setRequestHeader(csrfHeader, csrfToken);
        });
    }
})();
```

So at this point, Spring csrf is enabled, and each of my wicket ajax requests 
provides a 'x-xsrf-token' request header. Does this sound like a reasonable 
solution? Are there any suggestions on improving this in some way?

Thank you again for your time.

Jonathan Babie


________________________________
From: Jonathan Babie
Sent: Monday, September 22, 2025 5:41 PM
To: Wicket User Group <[email protected]>
Subject: Spring Boot 3 & Wicket 10 CSRF Configuration Question

Hello,

We are working on a new application which is using Spring Security (Spring Boot 
3.5.3) and Wicket (10.5.0), and we're encountering some issues with Spring CSRF:

Based on Wicket documentation for CSRFprevention, we have the following in our 
WebApplication init():
```
setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
getRequestCycleListeners().add(new ResourceIsolationRequestCycleListener());
```

Then, on the side of Spring Security, we have CSRF enabled (default behavior).

With Spring CSRF enabled, all of our form ajax requests fail silently with a 
403 forbidden error being logged in dev tools:
```
Request URL: http://localhost:8080/myapp/{encryptedurl}
Request Method: POST
Status Code: 403 Forbidden
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin
```

My request headers contains a cookie with the XSRF-TOKEN, but this is not being 
leveraged in any way currently.

If I disable Spring CSRF, everything works as expected.

Based on the research I've done for this, I need to essentially add an 
'X-XSRF-TOKEN' request header which contains the value of my xsrf-token cookie 
value but I couldn't find a Wicket hook to be able to do this and had a few 
questions:

  1.
Should we be enabling Spring CSRF in conjunction with Wicket's CSRF prevention 
mechanism?
  2.
If so, is there some hook to make these two work together seamlessly?

I was trying to address this via various listeners in my web application init, 
but was unsuccessful.

We're hoping since Spring is such a popular framework, someone else has 
experienced this / there's a clean solution. Please let me know if you need 
anymore information and thank you for your time.

Thank you,

Jonathan Babie

Notice: This communication, including any attachments, is intended solely for 
the use of the individual or entity to which it is addressed. This 
communication may contain information that is protected from disclosure under 
State and/or Federal law. Please notify the sender immediately if you have 
received this communication in error and delete this email from your system. If 
you are not the intended recipient, you are requested not to disclose, copy, 
distribute or take any action in reliance on the contents of this information.

Reply via email to