Can not disable CSRF for only 1 action in CakePHP 5.0.5?

I am using CakePHP 5.0.5 to write an App that connect to Strava and get running activities for users.

Strava require a webhook so that it can push update event of user activity to my app. That is why I have to disable CSRF for that webhook action.

My webhook action is:

public function webhook()
        // Event call back
        if ($this->request->is('post')) {
            $object_type = $this->request->getQuery('object_type');

            if (!is_null($object_type)){
               //do something later

            $this->set('result', 'OK');
            $this->viewBuilder()->setOption('serialize', ['result']);
        // Webhook subscription validation
        if ($this->request->is('get')) {
            $subcribe_result = $this->request->getQuery('hub_challenge');

            if (!is_null($subcribe_result)){
            $this->set('hub.challenge', $subcribe_result);
            $this->viewBuilder()->setOption('serialize', ['hub.challenge']);

I also disable CSRF for that webhook action like this:

public function initialize(): void
        $this->Authentication->allowUnauthenticated(['webhook', 'webhook.json']);



    public function beforeFilter(\Cake\Event\EventInterface $event)
        // Check if the current action is the one for which you want to disable CSRF protection
        if (($this->getRequest()->getParam('action') === 'webhook.json') || ($this->getRequest()->getParam('action') === 'webhook')) {

I also read Documentation for CakePHP 5, only find solution to disable CSRF for all actions which has prefix of something (“API”) in example below:

$csrf = new CsrfProtectionMiddleware();

    // Token check will be skipped when callback returns `true`.
    $csrf->skipCheckCallback(function ($request) {
        // Skip token check for API URLs.
        if ($request->getParam('prefix') === 'Api') {
            return true;

How do I disable CSRF for only 1 specific action of a specific controller ?

In your src/Application.php you can adjust the csrf middleware object before its enqueued in the middlewarequeue.

$csrf = new CsrfProtectionMiddleware([
    'httponly' => true,
$csrf->skipCheckCallback(function (ServerRequest $request) {
    if (
        $request->getParam('controller') === 'MyController' &&
        $request->getParam('action') === 'myAction'
    ) {
        return true;

    return false;

    // all the other middlewares
1 Like

Thank you Mr. KevinPfeifer,

It works like a charm. You save my day.