Skip to content

Instantly share code, notes, and snippets.

@1cg
Last active April 15, 2024 03:52
Show Gist options
  • Select an option

  • Save 1cg/05feb956f9de8ecee02dd74acee5ffe1 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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
Copy Markdown

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
Copy Markdown

@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
Copy Markdown

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
Copy Markdown

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown

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
Copy Markdown

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