Skip to content

Instantly share code, notes, and snippets.

@1cg
Last active April 15, 2024 03:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1cg/05feb956f9de8ecee02dd74acee5ffe1 to your computer and use it in GitHub Desktop.
Save 1cg/05feb956f9de8ecee02dd74acee5ffe1 to your computer and use it in GitHub Desktop.

CRSF Handling

Handling CRSF in htmx is server-side platform dependent, but typically involves something like the following to add a token to a header or parameter:

Vanilla JS

In pure javascript you can listen to the htmx:configRequest event and set the token there:

   document.body.addEventListener('htmx:configRequest', function(evt) {
      evt.detail.headers['X-CSRFToken'] = getToken();
    });

htmx JS api

Using the htmx javascript api, you can clean the above up a bit:

   htmx.on('htmx:configRequest', function(evt) {
      evt.detail.headers['X-CSRFToken'] = getToken();
    });

hyperscript

Finally, if you are using hyperscript, you can add the following to the body tag:

  <body _="on htmx:configRequest(headers) set headers['X-CSRFToken'] to getToken()">
     ...
  </body>

Platforms

Below are examples of setting the CSRT for various server side platforms.

Django

???

@simkimsia
Copy link

if this is okay https://gist.github.com/simkimsia/d602116b35d143de98afc729f8d3276f let me know, then I be happy to add that in.

I personally like to add a few more use cases within the (Django + htmx) domain such as

  1. a link that's HTTP POST and works with Django csrf token
  2. a form that's HTTP POST and works with Django csrf token
  3. a nested dropdown that works with Django backend (views.py and urls.py)

If that's too much, it's okay too

@adamchainz
Copy link

The POST link and nested dropdown should both pass CSRF if you set up the header as with my snippet. The form case should work using {% csrf_token %} like a non-htmx form, but it's probably worth documeting this.

There's one caveat as well - Django rotates the CSRF token on login/logout, so after these cases the page will need reloading or updating to update the token being added to the header by the JS.

@simkimsia
Copy link

@adamchainz did you see my fork of your gist? I kinda combine your gist with @1cg suggestion of meta tag and drop app.js

Is dropping app.js problematic from the XSS prevention pov?

As for updating CSRF token, I need to test this tomorrow. it's past midnight my place, I need to 😴 😄

@adamchainz
Copy link

There's no XSS risk from the snippet in your gist, but I'd recommend not using any inline <script> tags so you can use a strong Content Security Policy (or make it easier to migrate to one in the future). I think any documentation examples should follow that guideline.

@mallin
Copy link

mallin commented Jan 8, 2021

Virtually every server-side web app framework will use CSRF tokens. Maybe that makes this a common enough requirement that it's worth adding something like an hx-header attribute so that one could write <body hx-header="X-CSRFToken: {{ csrf_token }}"> and have that header be added to all HTMX requests made from elements within the body?

@1cg
Copy link
Author

1cg commented Jan 8, 2021

I think I'd like to split the docs into two different sections:

  1. General CRSF techniques
  2. Backend specific documentation

I'd like to use @adamchainz https://github.com/adamchainz/django-htmx as an example of how to build a back end integration.

Does that sound reasonable?

@1cg
Copy link
Author

1cg commented Jan 8, 2021

@mallin Yeah, I'm leaning heavily towards the hx-header attribute. This is very common, and it stinks you have to kick out to JS.

@simkimsia
Copy link

There's no XSS risk from the snippet in your gist, but I'd recommend not using any inline <script> tags so you can use a strong Content Security Policy (or make it easier to migrate to one in the future). I think any documentation examples should follow that guideline.

copy that I think I will work on the updating token part and then wait for @1cg potential change to add hx-csrf attribute

@simkimsia
Copy link

Does that sound reasonable?

yes @1cg as a newbie to HTMx this structure is okay but would be better with a getting started for django users section or subsection

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment