Hi all!
Its me again …
For new project I’ve set up minimal configuration of a REST-Api.
For authenication I use a bearer token. This works fine for
simple and more complext GET requests.
The problem arises with “unsave request”, in my case i.e. a PUT request.
For testing I use cURL on CLI from another machine.
In my simple implementation there is a method to get a valid CSRF token to use
it for the PUT request. I allways get an 403 error and in system log
I see:
The action could not be executed because you supplied no or the wrong CSRF protection token.
I’m shure there is missing something - but what? May be Im blind…
Here my test system:
Policy.yaml:
roles:
'Acme.Rest:PseudoUser':
privileges:
-
privilegeTarget: 'Acme.Rest:PseudoUser.ProductActions'
permission: GRANT
privilegeTargets:
'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege':
'Acme.Rest:PseudoUser.ProductActions':
matcher: 'method(Acme\Rest\Controller\ProductController->.*Action())'
Routes.yaml (excerpt):
-
name: 'product update'
uriPattern: 'product/update'
defaults:
'@package': 'Acme.Rest'
'@controller': 'Product'
'@action': 'update'
'@format': 'json'
httpMethods: ['PUT']
ProductController:
class ProductController extends RestController
{
/**
* @Flow\Inject
* @var Context
*/
protected $securityContext;
[...]
public function csrfGetterAction()
{
$tokenInfo = [ '__csrfToken' => $this->securityContext->getCsrfProtectionToken() ];
$this->view->setVariablesToRender( ['tokenInfo'] );
$this->view->assign('tokenInfo', $tokenInfo );
$this->response->setStatusCode(200);
}
/**
* public function updateAction
*
* only for testing - this method does nothing!
*
* @param string $productName
* @return void
*/
public function updateAction( string $productName )
{
$this->view->setVariablesToRender( ['result'] );
$this->view->assign('result', [ "product" => $productName, "b" => 'update/PUT' ] );
$this->response->setStatusCode(200);
}
My cURL requests:
First get CSRF token
curl -c cookies.txt -b cookies.txt -i -X GET -H "Authorization: Bearer ...." https://example.com/product/csrf
delivers something like this:
HTTP/1.1 200 OK
Date: Fri, 04 Apr 2025 14:33:47 GMT
Server: Apache/2.4.41 (Ubuntu)
X-Flow-Powered: Flow/8.3
Set-Cookie: Neos_Flow_Session=BnFGiUiu1wLrpWbpcsNh7quqLnFQZoF1; Path=/; HttpOnly; SameSite=lax
Transfer-Encoding: chunked
Content-Type: application/json
{"__csrfToken":"bb674a7d6b757e6a5093375e19046f73"}
now the PUT request:
curl -c cookies.txt -b cookies.txt -i -X PUT -H "Authorization: Bearer ..." -d '{"__csrfToken":"bb674a7d6b757e6a5093375e19046f73","productName":"lambda"}' https://example.com/product/update
delivers:
HTTP/1.1 403 Forbidden
Date: Fri, 04 Apr 2025 14:34:01 GMT
Server: Apache/2.4.41 (Ubuntu)
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
[...]
For to be shure, I’ve checked the token by calling again https://example.com/product/csrf
=> sends same CSRF token as above!
Now my question: what I missing here?
I’ve spend houres to solve this problem but I’m stuck…
Does some have an idea?
Thx for any hint!