Skip to content

Commit

Permalink
EZP-27996: "Remember me" doesn't retrieve the current user from Repos…
Browse files Browse the repository at this point in the history
…itory (#2106)

* EZP-27996: "Remember me" doesn't retrieve the current user from Repository

* fixup! EZP-27996: "Remember me" doesn't retrieve the current user from Repository

* Throw rather than return null

* fixup! Throw rather than return null

* fixup! fixup! Throw rather than return null
  • Loading branch information
glye authored and andrerom committed Nov 16, 2017
1 parent 771ac85 commit 730fb7a
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 1 deletion.
Expand Up @@ -20,7 +20,9 @@ class SecurityPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!($container->hasDefinition('security.authentication.provider.dao') && $container->hasDefinition('security.authentication.provider.anonymous'))) {
if (!($container->hasDefinition('security.authentication.provider.dao') &&
$container->hasDefinition('security.authentication.provider.rememberme') &&
$container->hasDefinition('security.authentication.provider.anonymous'))) {
return;
}

Expand All @@ -34,6 +36,12 @@ public function process(ContainerBuilder $container)
array($repositoryReference)
);

$rememberMeAuthenticationProviderDef = $container->findDefinition('security.authentication.provider.rememberme');
$rememberMeAuthenticationProviderDef->addMethodCall(
'setRepository',
array($repositoryReference)
);

$anonymousAuthenticationProviderDef = $container->findDefinition('security.authentication.provider.anonymous');
$anonymousAuthenticationProviderDef->addMethodCall(
'setRepository',
Expand Down
@@ -1,5 +1,6 @@
parameters:
security.authentication.provider.dao.class: eZ\Publish\Core\MVC\Symfony\Security\Authentication\RepositoryAuthenticationProvider
security.authentication.provider.rememberme.class: eZ\Publish\Core\MVC\Symfony\Security\Authentication\RememberMeRepositoryAuthenticationProvider
security.authentication.provider.anonymous.class: eZ\Publish\Core\MVC\Symfony\Security\Authentication\AnonymousAuthenticationProvider
security.authentication.success_handler.class: eZ\Publish\Core\MVC\Symfony\Security\Authentication\DefaultAuthenticationSuccessHandler
ezpublish.security.user_provider.class: eZ\Publish\Core\MVC\Symfony\Security\User\Provider
Expand Down
Expand Up @@ -20,6 +20,7 @@ protected function setUp()
{
parent::setUp();
$this->setDefinition('security.authentication.provider.dao', new Definition());
$this->setDefinition('security.authentication.provider.rememberme', new Definition());
$this->setDefinition('security.authentication.provider.anonymous', new Definition());
$this->setDefinition('security.http_utils', new Definition());
$this->setDefinition('security.authentication.success_handler', new Definition());
Expand All @@ -38,6 +39,11 @@ public function testAlteredDaoAuthenticationProvider()
'setRepository',
array(new Reference('ezpublish.api.repository'))
);
$this->assertContainerBuilderHasServiceDefinitionWithMethodCall(
'security.authentication.provider.rememberme',
'setRepository',
array(new Reference('ezpublish.api.repository'))
);
$this->assertContainerBuilderHasServiceDefinitionWithMethodCall(
'security.authentication.provider.anonymous',
'setRepository',
Expand Down
@@ -0,0 +1,44 @@
<?php

/**
* File containing the RememberMeRepositoryAuthenticationProvider class.
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace eZ\Publish\Core\MVC\Symfony\Security\Authentication;

use eZ\Publish\API\Repository\Repository;
use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

class RememberMeRepositoryAuthenticationProvider extends RememberMeAuthenticationProvider
{
/**
* @var \eZ\Publish\API\Repository\Repository
*/
private $repository;

public function setRepository(Repository $repository)
{
$this->repository = $repository;
}

/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
$authenticatedToken = parent::authenticate($token);
if (empty($authenticatedToken)) {
throw new AuthenticationException('The token is not supported by this authentication provider.');
}

$this->repository->getPermissionResolver()->setCurrentUserReference(
$authenticatedToken->getUser()->getAPIUser()
);

return $authenticatedToken;
}
}
@@ -0,0 +1,165 @@
<?php

/**
* File containing the RememberMeRepositoryAuthenticationProviderTest class.
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace eZ\Publish\Core\MVC\Symfony\Security\Tests\Authentication;

use eZ\Publish\API\Repository\Repository;
use eZ\Publish\API\Repository\Values\User\User as ApiUser;
use eZ\Publish\API\Repository\Values\User\UserReference;
use eZ\Publish\Core\MVC\Symfony\Security\Authentication\RememberMeRepositoryAuthenticationProvider;
use eZ\Publish\Core\MVC\Symfony\Security\User;
use eZ\Publish\Core\Repository\Helper\LimitationService;
use eZ\Publish\Core\Repository\Helper\RoleDomainMapper;
use eZ\Publish\Core\Repository\Permission\PermissionResolver;
use eZ\Publish\SPI\Persistence\User\Handler as UserHandler;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class RememberMeRepositoryAuthenticationProviderTest extends TestCase
{
/**
* @var RememberMeRepositoryAuthenticationProvider
*/
private $authProvider;

/**
* @var \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\API\Repository\Repository
*/
private $repository;

protected function setUp()
{
parent::setUp();

$this->repository = $this->getMock(Repository::class);
$this->authProvider = new RememberMeRepositoryAuthenticationProvider(
$this->getMock(UserCheckerInterface::class),
'my secret',
'my provider secret'
);
$this->authProvider->setRepository($this->repository);
}

/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
* @expectedExceptionMessage The token is not supported by this authentication provider.
*/
public function testAuthenticateUnsupportedToken()
{
$anonymousToken = $this
->getMockBuilder(AnonymousToken::class)
->setConstructorArgs(['secret', $this->getMock(UserInterface::class)])
->getMock();
$this->authProvider->authenticate($anonymousToken);
}

/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
* @expectedExceptionMessage The token is not supported by this authentication provider.
*/
public function testAuthenticateWrongProviderKey()
{
$user = $this->getMock(UserInterface::class);
$user
->expects($this->any())
->method('getRoles')
->will($this->returnValue([]));

$rememberMeToken = $this
->getMockBuilder(RememberMeToken::class)
->setConstructorArgs([$user, 'wrong provider secret', 'my secret'])
->getMock();
$rememberMeToken
->expects($this->any())
->method('getProviderKey')
->will($this->returnValue('wrong provider secret'));

$this->authProvider->authenticate($rememberMeToken);
}

/**
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
*/
public function testAuthenticateWrongSecret()
{
$user = $this->getMock(UserInterface::class);
$user
->expects($this->any())
->method('getRoles')
->will($this->returnValue([]));

$rememberMeToken = $this
->getMockBuilder(RememberMeToken::class)
->setConstructorArgs([$user, 'my provider secret', 'the wrong secret'])
->getMock();
$rememberMeToken
->expects($this->any())
->method('getProviderKey')
->will($this->returnValue('my provider secret'));
$rememberMeToken
->expects($this->any())
->method('getSecret')
->will($this->returnValue('the wrong secret'));

$this->authProvider->authenticate($rememberMeToken);
}

public function testAuthenticate()
{
$this->repository
->expects($this->once())
->method('getPermissionResolver')
->will($this->returnValue($this->getPermissionResolverMock()));

$apiUser = $this->getMock(ApiUser::class);
$apiUser
->expects($this->any())
->method('getUserId')
->will($this->returnValue(42));

$tokenUser = new User($apiUser);
$rememberMeToken = new RememberMeToken($tokenUser, 'my provider secret', 'my secret');

$authenticatedToken = $this->authProvider->authenticate($rememberMeToken);
$this->assertEquals(
[$rememberMeToken->getProviderKey(), $rememberMeToken->getSecret(), $rememberMeToken->getUsername()],
[$authenticatedToken->getProviderKey(), $authenticatedToken->getSecret(), $authenticatedToken->getUsername()]
);
}

/**
* @return \eZ\Publish\Core\Repository\Permission\PermissionResolver|\PHPUnit_Framework_MockObject_MockObject
*/
private function getPermissionResolverMock()
{
return $this
->getMockBuilder(PermissionResolver::class)
->setMethods(null)
->setConstructorArgs(
[
$this
->getMockBuilder(RoleDomainMapper::class)
->disableOriginalConstructor()
->getMock(),
$this
->getMockBuilder(LimitationService::class)
->getMock(),
$this
->getMockBuilder(UserHandler::class)
->getMock(),
$this
->getMockBuilder(UserReference::class)
->getMock(),
]
)
->getMock();
}
}

0 comments on commit 730fb7a

Please sign in to comment.