Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FormProtectionComponent with Authentication plugin active #17585

Open
andrii-pukhalevych opened this issue Feb 15, 2024 · 2 comments
Open

FormProtectionComponent with Authentication plugin active #17585

andrii-pukhalevych opened this issue Feb 15, 2024 · 2 comments
Labels
Milestone

Comments

@andrii-pukhalevych
Copy link
Contributor

andrii-pukhalevych commented Feb 15, 2024

Description

When FormProtectionComponent is enabled with Authentication plugin active,
calling AuthenticationComponent::setIdentity() in parallel requests (ajax, generated image or another tab) causes call of SessionAuthenticator::clearIdentity() and then Session::renew().

Result is that session id is changed, and main form submit will be failed with BadRequestException.
Not sure if its bug, but at least it will be doccumented here.
In my case I have to override FormProtectionComponent::_getSessionId() to resolve it.

CakePHP Version

5.0.4

PHP Version

8.1

@markstory
Copy link
Member

When FormProtectionComponent is enabled with Authentication plugin active,
calling AuthenticationComponent::setIdentity() in parallel requests (ajax, generated image or another tab) causes call of SessionAuthenticator::clearIdentity() and then Session::renew().

This is kind of expected, you're setting the identity which could be privilege escalation which should require a form protection tokens to be rotated. This is important as it prevents form reuse after logout or login.

@markstory markstory added this to the 5.0.6 milestone Feb 15, 2024
@andrii-pukhalevych
Copy link
Contributor Author

andrii-pukhalevych commented Feb 16, 2024

Tried to wrap it by overriding FormProtectionComponent::_getSessionId() and return user id:

<?php
declare(strict_types=1);

namespace App\Controller\Component;

use Cake\Routing\Router;

class FormProtectionComponent extends \Cake\Controller\Component\FormProtectionComponent {

	protected function _getSessionId(): string {
		return static::getSessionId();
	}

	public static function getSessionId(): string {
		$session = Router::getRequest()->getSession();
		$session->start();

		/** @var \Authentication\Identity|null $Itentity */
		$Identity = $session->read('Auth');
		if (null !== $Identity) {
			return json_encode([$Identity->getIdentifier(), $Identity->get('is_deactivated')]);
		}

		return $session->id();
	}
}

but found that hidden input value is generated by FormHelper::_getFormProtectorSessionId(), not by FormProtectionComponent. Methods code is copy-pasted, ->getSession()->id() in both methods.

Had to override also FormHelper::_getFormProtectorSessionId().

<?php
declare(strict_types=1);

namespace App\View\Helper;

class FormHelper extends \Cake\View\Helper\FormHelper {

	protected function _getFormProtectorSessionId(): string {
		return \App\Controller\Component\FormProtectionComponent::getSessionId();
	}
}

@markstory markstory modified the milestones: 5.0.6, 5.0.7 Mar 9, 2024
@markstory markstory modified the milestones: 5.0.7, 5.0.8 Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants