Skip to content

Commit

Permalink
[Security] Fixed problem with losing ROLE_PREVIOUS_ADMIN role.
Browse files Browse the repository at this point in the history
  • Loading branch information
pawaclawczyk authored and fabpot committed Dec 29, 2013
1 parent c59f52b commit a7baa3b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
Expand Up @@ -19,6 +19,7 @@
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\SwitchUserRole;

/**
* UserProviderInterface retrieves users for UsernamePasswordToken tokens.
Expand Down Expand Up @@ -92,7 +93,7 @@ public function authenticate(TokenInterface $token)
throw $e;
}

$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles());
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
$authenticatedToken->setAttributes($token->getAttributes());

return $authenticatedToken;
Expand All @@ -106,6 +107,29 @@ public function supports(TokenInterface $token)
return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey();
}

/**
* Retrieves roles from user and appends SwitchUserRole if original token contained one.
*
* @param UserInterface $user The user
* @param TokenInterface $token The token
*
* @return Role[] The user roles
*/
private function getRoles(UserInterface $user, TokenInterface $token)
{
$roles = $user->getRoles();

foreach ($token->getRoles() as $role) {
if ($role instanceof SwitchUserRole) {
$roles[] = $role;

break;
}
}

return $roles;
}

/**
* Retrieves the user from an implementation-specific location.
*
Expand Down
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;

class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
Expand Down Expand Up @@ -172,6 +173,11 @@ public function testAuthenticate()
->will($this->returnValue('foo'))
;

$token->expects($this->once())
->method('getRoles')
->will($this->returnValue(array()))
;

$authToken = $provider->authenticate($token);

$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
Expand All @@ -181,9 +187,45 @@ public function testAuthenticate()
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
}

public function testAuthenticateWithPreservingRoleSwitchUserRole()
{
$user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
$user->expects($this->once())
->method('getRoles')
->will($this->returnValue(array('ROLE_FOO')))
;

$provider = $this->getProvider();
$provider->expects($this->once())
->method('retrieveUser')
->will($this->returnValue($user))
;

$token = $this->getSupportedToken();
$token->expects($this->once())
->method('getCredentials')
->will($this->returnValue('foo'))
;

$switchUserRole = new SwitchUserRole('foo', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
$token->expects($this->once())
->method('getRoles')
->will($this->returnValue(array($switchUserRole)))
;

$authToken = $provider->authenticate($token);

$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
$this->assertSame($user, $authToken->getUser());
$this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
$this->assertContains($switchUserRole, $authToken->getRoles());
$this->assertEquals('foo', $authToken->getCredentials());
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
}

protected function getSupportedToken()
{
$mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getProviderKey'), array(), '', false);
$mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getProviderKey', 'getRoles'), array(), '', false);
$mock
->expects($this->any())
->method('getProviderKey')
Expand Down

0 comments on commit a7baa3b

Please sign in to comment.