-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support automatically adding CSRF token when using the custom processors #36
Comments
That seems like a worthwhile feature. With |
More information can be found at: https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#advanced-integration-features. But basically, Thymeleaf's Spring integration utilizes the RequestDataValueProcessor to transparently add hidden fields to "enable security features like e.g. protection agains CSRF (Cross-Site Request Forgery)."
|
Would be nice to have this indeed! |
@wimdeblauwe do you see this feature being on this library's roadmap in the near future or...? |
If I would know how to do it, I would love to add it. I now asked thymeleaf/thymeleaf#934 if somebody might now the way how to do it. |
Or the attribute process could add an extra |
This could also be accomplished in htmx itself by adding an eventListener that adds the csrf token to the request. The spring security docs document how this might be done with a js library. For HTMX it could be done with something like this (please forgive me, I haven't actually run this code): <head>
<meta name="_csrf" th:content="${_csrf.token}"/>
<script>
document.body.addEventListener('htmx:configRequest', function(evt) {
evt.detail.headers['X-XSRF-TOKEN'] = document.querySelector('meta[name="_csrf"]').content
});
</script>
</head> This would cover form submissions as well as requests triggered by the attributes |
I'm trying @vrish88's approach right now and it does look promising. However, for some reason the CSRF token being sent is not the same token as the server expects in the protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// snip to line 61
CsrfToken csrfToken = deferredCsrfToken.get();
String actualToken = this.requestHandler.resolveCsrfTokenValue(request, csrfToken); Also minor note, the token header name is slightly different for me (Spring Security 6). It's also worth inserting the name into the header as this should adapt to Security config changes. <head>
<script src="https://unpkg.com/[email protected]"></script>
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
<script>
document.addEventListener("DOMContentLoaded", function() {
var token = document.querySelector('meta[name="_csrf"]').content;
var headerName = document.querySelector('meta[name="_csrf_header"]').content;
document.body.addEventListener('htmx:configRequest', function(evt) {
evt.detail.headers[headerName] = token;
});
});
</script>
</head> The token being sent automatically by Thymeleaf works, so something is clearly missing from this approach. |
Is the CSRF token perhaps changing on different requests? Maybe each request needs to send along a new CSRF as a HX-Trigger that gets pulled in? Is the CSRF token static for an entire session or generated new with each request? |
Just for reference, in the spirit of the above javascript solutions to set the CSRF header for every htmx request, I've been using this: <!--/* add the CSRF header to all htmx requests */-->
<script th:inline="javascript">
/*<![CDATA[*/
document.body.addEventListener('htmx:configRequest', (event) => {
const csrfHeader = /*[[${_csrf.headerName}]]*/ 'X-Sample-CSRF-Header';
const csrfToken = /*[[${_csrf.token}]]*/ 'sample-csrf-token';
event.detail.headers[csrfHeader] = csrfToken;
});
/*]]>*/
</script> This lets Thymeleaf inject the CSRF header name and token directly into the javascript template, as opposed to meta tags. Works with Spring Boot 3. |
I'm pretty sure HTMX just sends all the form inputs (including the thymeleaf-generated ones), so as long as |
A button that just triggers a delete of something might be in many cases not part of a form, but just an |
That's a good example. If it isn't in a form, you can add the csrf token manually I guess, and tell HTMX about it with the |
This is how I did it:
|
I see a lot of solutions, but most of them are with Thymeleaf. What if you don't use Thymeleaf? |
When submitting forms, Thymeleaf's
th:action
attribute adds required CSRF tokens automatically. It seems to me that this feature isn't supported when using, for examplehx:post
on a form.For reference, it would eliminate the need to manually add
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
to all of my newly-converted-to htmx forms.Is this something that you envisage will be supported?
The text was updated successfully, but these errors were encountered: