CSRF Protection#
Configure CSRF protection for Inertia applications.
See also
Official Inertia.js docs: CSRF Protection
Overview#
Unsafe requests need a CSRF token. litestar-vite exposes that token through
page state, so browser code does not need to read the CSRF cookie directly.
Recommended Litestar Configuration#
For litestar-vite helpers and generated Inertia scaffolds, the minimal
recommended setup is:
from litestar import Litestar
from litestar.config.csrf import CSRFConfig
app = Litestar(
csrf_config=CSRFConfig(
secret="your-secret-key-min-32-chars-long",
cookie_httponly=True,
),
)
This keeps Litestar’s default cookie/header names (csrftoken and
x-csrftoken) and works with cookie_httponly=True because the browser
reads the token from injected page state instead of the cookie itself.
Note
If you intentionally use a client library that reads the CSRF cookie directly,
such as a legacy Axios XSRF-cookie setup, keep cookie_httponly=False and
align the cookie/header names explicitly for that client. Consumers of
litestar-vite-plugin/helpers do not need manual alignment: configured names
are injected into browser state and used automatically.
Token in Templates#
The CSRF token is available in templates:
<!-- Hidden input for traditional forms -->
{{ csrf_input }}
<!-- Or access the token directly -->
<meta name="csrf-token" content="{{ csrf_token }}">
Token in Props#
The csrf_token prop is automatically included in shared props:
interface SharedProps {
csrf_token: string;
// ...other props
}
const { csrf_token } = usePage<SharedProps>().props;
Inertia Client Visits#
The generated Inertia templates wire Litestar’s default CSRF header into global
visit options so unsafe Inertia requests work with cookie_httponly=True:
import { createInertiaApp } from "@inertiajs/react";
import { csrfHeaders } from "litestar-vite-plugin/helpers";
createInertiaApp({
defaults: {
visitOptions: (_href, options) => ({
headers: csrfHeaders(options.headers ?? {}),
}),
},
// ...
});
The same pattern works for @inertiajs/vue3 and @inertiajs/svelte.
SPA Mode#
In SPA mode, CSRF tokens are injected via HTML transformation:
// Available as a global variable
const token = window.__LITESTAR_CSRF__;
Configure the variable name:
from litestar_vite.config import SPAConfig
ViteConfig(
spa=SPAConfig(
inject_csrf=True,
csrf_var_name="__LITESTAR_CSRF__", # Default
),
)
CSRF Helper Functions#
The litestar-vite-plugin/helpers package provides utility functions for CSRF token handling:
import {
csrfFetch,
csrfHeaders,
getCsrfHeaderName,
getCsrfToken,
} from 'litestar-vite-plugin/helpers';
// Get CSRF token (from window.__LITESTAR_CSRF__, meta tag, or Inertia props)
const token = getCsrfToken();
// Get the configured header name and a ready-to-use headers object
const headerName = getCsrfHeaderName();
const headers = csrfHeaders();
// Make a fetch request with CSRF token automatically included
await csrfFetch('/api/submit', {
method: 'POST',
body: JSON.stringify(data),
});
These helpers work in both SPA and template modes, automatically detecting the
token source. When CSRFConfig customizes cookie_name or header_name,
the HTML handler injects window.__LITESTAR_CSRF_COOKIE_NAME__ and
window.__LITESTAR_CSRF_HEADER_NAME__ alongside the token, so no separate
JavaScript configuration is required.
Excluding Routes#
Exclude specific routes from CSRF protection:
CSRFConfig(
secret="...",
exclude=["/api/webhook", "/api/health"],
)
Troubleshooting#
403 Forbidden errors:
Verify the request sends Litestar’s default CSRF header (
x-csrftoken/X-CSRFToken)Verify the CSRF cookie is set on the correct domain/path
If you use a cookie-readable client, verify
cookie_httponly=FalseIf you customized
header_name, the provided helpers follow it automatically. For hand-written fetch/XHR clients that do not usecsrfHeaders()orcsrfFetch(), make sure the client sends the same header.
Token not found:
Ensure CSRF middleware is registered
Check the token is present in injected page state (global, meta tag, or Inertia props)
Verify the token is included in the request headers
See Also#
Forms - Form handling