Symfony CSRF

I’m integrating PHPMaker (2026.10) with Symfony CSRF validation and I’m seeing inconsistent behavior between API requests and normal form submissions.


1. API request (FAILS CSRF)

Route:

phpmaker2026_azkayra_apiaction_dispatcher

CSRF data:

csrfId: submit  
tokenValue: kPVSrGtZarfBHpCN6tSx_Z2m

Cookies:

csrf-token_kPVSrGtZarfBHpCN6tSx_Z2m = csrf-token

:right_arrow: Cookie name is generated correctly, but Symfony CSRF validation still fails (403 Forbidden).


2. Standard form submit (WORKS)

Route:

add.platform_positions

CSRF data:

csrfId: submit  
tokenValue: 7H4Ft6-_3oDw6802i53BLKQf

Cookies:

csrf-token_ = csrf-token   (empty suffix)

:right_arrow: Despite the incomplete cookie key, the request passes CSRF validation.


Symfony validation code

if (!$tokenValue || !$this->csrfTokenManager->isTokenValid(new CsrfToken($csrfId, $tokenValue))) {
    throw new AccessDeniedHttpException('Invalid CSRF token');
}

Problem summary

The behavior is inconsistent:

  • In API requests:

    • PHPMaker generates a proper stateless CSRF cookie name:

      csrf-token_<token>
      
    • But Symfony still rejects the request.

  • In normal form submissions:

    • Cookie name is incomplete:

      csrf-token_
      
    • But Symfony accepts the request.


Question

Is this expected behavior in PHPMaker 2026 stateless CSRF implementation, or is there a mismatch in how generateCsrfToken() handles cookie generation between:

  • fetch/API submissions

  • standard form POST submissions

Also, what is the correct/official way to make CSRF validation consistent across both flows without breaking Symfony security or modifying its core CSRF logic?


If there is a recommended configuration or integration pattern for PHPMaker + Symfony stateless CSRF, I would appreciate guidance.

Note that API does not use CSRF token by default, it uses JWT token to protect the API, it is a different mechanism, there is no need to send CSRF token to API.

First, make sure your route "phpmaker2026_azkayra_apiaction_dispatcher" is an API route. An API route URL must starts with /api/. In your controller, you should have #[Route('/api')]. Then it is protected by JWT.

If your route is not under /api/, then CSRF applies. (I believe that is your case.) You may read how Symfony statelesss CSRF protection works here:

the request is validated using a cookie and a CsrfToken . If the cookie is found, it must contain the same value as the CsrfToken.

I'm not sure why you see incomplete cookie name, in a normal form submission (HTTP POST only), there is a cookie like csrf-token_L_TNm-PI83GEzGBWWcl574X3=csrf-token and a form data like _csrf_token=L_TNm-PI83GEzGBWWcl574X3 so it is valid.

When you submit your form values to your own "API" (i.e. "phpmaker2026_azkayrapiaction_dispatcher"), make sure you send _csrf_token=xxx where xxx match your cookie name.

Also, as above docs says:

A JavaScript snippet on the client side is responsible for performing this double-submission. The token value should be regenerated on every request using a cryptographically secure random generator.

Before submission, make sure you call ew.generateCsrfToken() first, which find all input[name=_csrf_token] in the page and generate a new token. (Old tokens won't work.)