8000 [Security] CSRF token validation failure in functional tests · Issue #50209 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Security] CSRF token validation failure in functional tests #50209

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

Closed
mmarchois opened this issue May 2, 2023 · 3 comments
Closed

[Security] CSRF token validation failure in functional tests #50209

mmarchois opened this issue May 2, 2023 · 3 comments

Comments

@mmarchois
Copy link
Contributor
mmarchois commented May 2, 2023

Symfony version(s) affected

6.2.8

Description

Since the upgrade to version 6.2.8, the validation of csrf tokens in our functional tests does not work anymore. All my tests throw the exception "Invalid CSRF token".

How to reproduce

The controller i want to test :

// ...
public function __invoke(Request $request): Response
{
        // ...
        $csrfToken = new CsrfToken('token-name', $request->request->get('token'));
        if (!$this->csrfTokenManager->isTokenValid($csrfToken)) {
            throw new BadRequestHttpException('Invalid CSRF token');
        }
}

The functional test :

// ...
use SessionHelper;

public function testDelete(): void
{
    $client = $this->loginUser($user) ;
    $client->request('DELETE', 'my-url', [
        'token' => $this->generateCsrfToken($client, 'token-name'),
    ]) ;
}

Token generation on the test side :

trait SessionHelper
{
    public function getSession(KernelBrowser $client) : Session
    {
        $cookie = $client->getCookieJar()->get('MOCKSESSID') ;

        // create a new session object
        $container = static::getContainer() ;
        $sessionSavePath = $container->getParameter('session.save_path') ;
        $sessionStorage = new MockFileSessionStorage($sessionSavePath) ;
        $session = new Session($sessionStorage) ;
        $session->setId($cookie->getValue()) ;
        $session->start() ;

        return $session ;
    }

    public function generateCsrfToken(KernelBrowser $client, string $tokenId) : string
    {
        $session = $this->getSession($client) ;
        $container = static::getContainer() ;
        $tokenGenerator = $container->get('security.csrf.token_generator') ;
        $csrfToken = $tokenGenerator->generateToken() ;
        $session->set(SessionTokenStorage::SESSION_NAMESPACE . "/{$tokenId}", $csrfToken) ;
        $session->save() ;

        return $csrfToken ;
    }
}

Note that this code worked in 6.2.7.

Possible Solution

No response

Additional Context

No response

@krciga22
Copy link
Contributor

Hi @mmarchois, I've taken a look at this issue and was able to recreate it on my system with two separate projects for 6.2.7 and 6.2.8. It looks like this issue is occurring in 6.2.8 due to a commit from Issue #49745. This commit sets/overwrites the session save_path config and container parameter to null if you don't specify a session handler_id in your framework config yaml. Do you currently have a session handler_id such as 'session.handler.native' or 'session.handler.native_file' defined in your framework config yaml? I tested both of these handler_ids and the test case appears to pass for both. I'm not sure why save_path=null is affecting the test case, but I'll take a deeper look and see what I can find.

commit e23be5834812b00b321f8cfc3a968b20546aa6f7

if (null === $config['handler_id']) {
    $config['save_path'] = null;
    $container->setAlias('session.handler', 'session.handler.native');
} else { 
    ...
}
framework:
    session:
        handler_id: 'session.handler.native'

@krciga22
Copy link
Contributor

After looking into this some more, it looks like the test case creates an instance of MockFileSessionStorage which has a save_path of '%kernel.cache_dir%/sessions' in 6.2.7, but then has a save_path of null (further defaulting to sys_get_temp_dir()) in 6.2.8 due to the fix in #49745.

The controller appears to use MockFileSessionStorageFactory which has a save_path of param('kernel.cache_dir').'/sessions' in both versions.

To fix the test case, as before you can specifcy a session handler_id in your framework config yaml, or use MockFileSessionStorageFactory in the test case instead of MockFileSessionStorage.

//$sessionStorage = new MockFileSessionStorage($sessionSavePath) ;
$factory = $this->getContainer()->get('session.storage.factory.mock_file');
$sessionStorage = $factory->createStorage(null);

@mmarchois
Copy link
Contributor Author

@krciga22 it works ! Many thanks for your help ! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
0