Skip to content

Custom stores

Greg Bowler edited this page Apr 22, 2026 · 1 revision

The package includes two token stores, but the API is designed so we can implement our own storage backend when needed.

When a custom store is useful

You might want a custom TokenStore when tokens need to live in:

  • a database table
  • Redis or another cache service
  • a framework-specific session abstraction
  • a distributed store shared between several application instances

What must be implemented

Extend GT\Csrf\TokenStore and implement these methods:

  • saveToken(string $token): void
  • verifyToken(string $token): void
  • consumeToken(string $token): void

The base class already provides token generation and the high-level verify() workflow.

Example skeleton

use GT\Csrf\Exception\CsrfTokenInvalidException;
use GT\Csrf\Exception\CsrfTokenSpentException;
use GT\Csrf\TokenStore;

class DatabaseTokenStore extends TokenStore {
	public function saveToken(string $token):void {
		// Persist the token as "not yet used".
	}

	public function verifyToken(string $token):void {
		$record = null; // Load from storage.

		if(!$record) {
			throw new CsrfTokenInvalidException($token);
		}

		if($record["used_at"] !== null) {
			throw new CsrfTokenSpentException(
				$token,
				$record["used_at"]
			);
		}
	}

	public function consumeToken(string $token):void {
		// Persist the current timestamp as the use time.
	}
}

Behaviour to preserve

When writing a custom store, it helps to preserve the same behaviour as the built-in stores:

  • a saved token should be valid exactly once
  • a consumed token should produce CsrfTokenSpentException
  • a missing token should produce CsrfTokenInvalidException
  • old tokens should be removable when a maximum count is exceeded

If you need a retention policy, getMaxTokens() exposes the configured limit from the base class.

Using the custom store

Once implemented, the custom store can be used anywhere a normal token store is expected:

$tokenStore = new DatabaseTokenStore();
$protector = new HTMLDocumentProtector($html, $tokenStore);

That includes both page protection and request verification.


The API reference is a compact summary of classes, constants and methods.

Clone this wiki locally