Kyrux
Back

CSRF

CSRF is automatically validated on POST, PUT, PATCH, and DELETE.

In HTML forms

<form method="POST" action="{{ url "criar_post" }}">
  {{ csrf_token }}
  <input type="text" name="titulo" placeholder="Title">
  <button type="submit">Publish</button>
</form>

{{ csrf_token }} automatically injects:

<input type="hidden" name="kyrux_csrf_token" value="abc123...">

In AJAX requests

The token sent must be the signed value — the same one {{ csrf_token }} injects into the hidden input (the kyrux_csrf cookie holds the raw value, which is not accepted). Read it from the input rendered on the page:

const token = document.querySelector('input[name="kyrux_csrf_token"]').value;

fetch('/api/posts/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': token,
    },
    body: JSON.stringify({ titulo: 'My Post' }),
});

Exempting API routes (Bearer token)

APIs authenticated via JWT (RequireAuth) don't use cookies — exempt the app's prefix from CSRF validation in Register:

import "kyrux/core/security/csrf"

csrf.Exempt("/api/")