Search by

xddesigners / silverstripe-csrf-hydrate

RVXD

Keep CSRF-protected forms and links working on full-page-cached Silverstripe pages: render them without a per-session SecurityID and hydrate a fresh token client-side. Includes automatic tagging of silverstripe/userforms forms.

Package info

github.com/xddesigners/silverstripe-csrf-hydrate

Type:silverstripe-vendormodule

pkg:composer/xddesigners/silverstripe-csrf-hydrate

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-09-17 09:02 UTC

This package is auto-updated.

Last update: 2026-09-17 09:08:50 UTC


README

Keep CSRF-protected forms and links working on full-page-cached pages.

When a page is full-page cached, its HTML is shared across all visitors — so it must not contain a per-session SecurityID (CSRF token). This module lets you render such forms/links without a token and inject a fresh one client-side: on load, a tiny script fetches the current session's token from a small endpoint and fills it in. Designed to pair with xddesigners/silverstripe-page-cache, but works with any full-page cache.

  • Endpoint /csrftoken returns the current session's token as JSON (no-store, same-origin).
  • client/dist/csrf-hydrate.js hydrates every [data-csrf-hydrate] link/form (and re-runs after AJAX injects new DOM). No jQuery.
  • silverstripe/userforms forms are auto-tagged when that module is installed — no template edits.

Why this is still CSRF-safe

The token endpoint only returns the current session's token to a same-origin, credentialed request; a cross-site page cannot read the response (no CORS), so it cannot steal a victim's token. A client with no JavaScript (including bots) never obtains a token, so a protected action simply cannot be performed by it — which is a useful side-effect against bot form spam and cart adds.

Requirements

  • PHP ^8.1
  • silverstripe/framework ^5 || ^6, silverstripe/cms ^5 || ^6

Tested against Silverstripe CMS 6 (with silverstripe/userforms ^7). CMS 5 uses the same APIs.

Installation

composer require xddesigners/silverstripe-csrf-hydrate

Then ?flush=all. The script and a <meta name="csrf-token-endpoint"> tag are added to every content page automatically; user-defined forms are tagged automatically.

Usage

User-defined forms (silverstripe/userforms)

Nothing to do — when userforms is installed, each UserForm is tagged with data-csrf-hydrate and its token is refreshed client-side. Cache the page containing the form and submissions keep working.

Your own forms and links

Render the form/link without a SecurityID and add data-csrf-hydrate:

// A form:
$form->setAttribute('data-csrf-hydrate', 'true');

// A GET action link that carries a token — strip it server-side, tag the link:
$link = preg_replace('/([?&])SecurityID=[^&]*/', '$1', $link);
// <a href="$link" data-csrf-hydrate> … </a>

The script appends ?SecurityID=<token> to tagged links and sets/creates the hidden SecurityID input on tagged forms. Clicks/submits are blocked until hydration completes, so a token-less request can never fire. After injecting a fragment via AJAX, call window.csrfHydrate() to hydrate it (the built-in MutationObserver also picks up most cases automatically).

Configuration

The token endpoint is registered at /csrftoken via a Director rule. To point the script somewhere else, change the meta tag (e.g. in a template) or override XD\CsrfHydrate\Extensions\CsrfHydrateControllerExtension.

License

BSD-3-Clause. See LICENSE.