Slim-Csrf icon indicating copy to clipboard operation
Slim-Csrf copied to clipboard

Sending CSRF name/value as request header does not work with Apache

Open euantorano opened this issue 3 months ago • 2 comments

Slim-Csrf supports reading the token names and values from HTTP request headers, which is useful when using AJAX and such. This functionality is implemented here: https://github.com/slimphp/Slim-Csrf/blob/1.x/src/Guard.php#L449

Unfortunately, this does not seem to work when serving PHP via fcgid on the Apache web server, as the HTTP headers are stripped.

It's taken me a lot of debugging to get here, but once you set the Apache LogLevel to LogLevel trace1 and send a request with the headers set, you'll see errors such as the following in the Apache error log:

[Wed Oct 29 14:32:35.792102 2025] [core:trace1] [pid 16352:tid 1960] util_script.c(77): [client ::1:50027] Not exporting header with invalid name as envvar: name, referer: http://localhost/system/create
[Wed Oct 29 14:32:35.792102 2025] [core:trace1] [pid 16352:tid 1960] util_script.c(77): [client ::1:50027] Not exporting header with invalid name as envvar: value, referer: http://localhost/system/create

Using Apache's mod_forensic, we can see the request coming in with the header intact:

+14756:690224c8:0|POST /system/create HTTP/1.1|Host:localhost|Connection:keep-alive|Content-Length:363|sec-ch-ua-platform:"Windows"|sec-ch-ua:"Microsoft Edge";v="141", "Not?A_Brand";v="8", "Chromium";v="141"|sec-ch-ua-mobile:?0|csrf_name:csrf690202736056c|X-Requested-With:XMLHttpRequest|User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0|Accept:application/json|Content-Type:application/json|csrf_value:xMqmCCFGUWeSDFlpR554QtPrjbaBjhv1d7YlrN1Uya7x+MJrFXBkVKVoaQpx+k4k4om41+K9IsdBj0Gbuzb/mQ==|Origin:http%3a//localhost|Sec-Fetch-Site:same-origin|Sec-Fetch-Mode:cors|Sec-Fetch-Dest:empty|Referer:http%3a//localhost/system/create|Accept-Encoding:gzip, deflate, br, zstd|Accept-Language:en-GB,en;q=0.9,en-US;q=0.8|Cookie:PHPSESSID=cjlal9vpd00c4ga4ldcmnovmqg
-14756:690224c8:0

This message is logged by Apache here: https://github.com/apache/httpd/blob/trunk/server/util_script.c#L72

To me, it looks like Apache doesn't like that the header contains an underscore (csrf_name and csrf_value become name and value respectively).

It might be useful to be able to customise the logic for the Guard::getTokenNameKey and Guard::getTokenValueKey logic.

As it stands, I've changed the logic to use a hyphen (-) rather than an underscore (-) by subclassing the Guard and re-implementing the two methods, and that resolved the problem.

euantorano avatar Oct 29 '25 14:10 euantorano

Hi @euantorano Yes, to make the TokenNameKey and TokenValueKey configurable would be the best solution. Until this is implemented, you may also use a custom middleware to copy the values from one header to another header, so that the Guard class can read the value with an underscore. Example (not tested):

final class CsrfHeaderFixMiddleware implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (!$request->hasHeader('csrf_name') && $request->hasHeader('csrf-name')) {
            $request = $request->withHeader('csrf_name', $request->getHeader('csrf-name'));
        }

        if (!$request->hasHeader('csrf_value') && $request->hasHeader('csrf-value')) {
            $request = $request->withHeader('csrf_value', $request->getHeader('csrf-value'));
        }

        return $handler->handle($request);
    }
}

Usage

$app->add(new Slim\Csrf\Guard($responseFactory));
$app->add(new App\Middleware\CsrfHeaderFixMiddleware()); // <--- after the Guard middleware to run it before the execution of the Guard  middlewaere

Feel free to create a PR that adds the needed setter-Methods.

odan avatar Nov 06 '25 18:11 odan

This is also solved in the 2.x branch, so we probably should look at tagging 2.0 to release it.

akrabat avatar Nov 06 '25 19:11 akrabat