Properly handles "post auth" tokens that have become not authenticated

Here is the flow:

A) You login using guard and are given a PostAuthGuardToken
B) Your user changes between requests - AbstractToken::setUser() and hasUserChanged() - which
    results in the Token becoming "not authenticated"
C) Something calls out to the security system, which then passes the no-longer-authed
    token back into the AuthenticationProviderManager
D) Because the PostauthGuardToken implements GuardTokenInterface, the provider responds
    to it. But, seeing that this is a no-longer-authed PostAuthGuardToken, it returns
    an AnonymousToken, which triggers logout
This commit is contained in:
Ryan Weaver 2015-05-17 17:29:55 -04:00
parent 873ed284d2
commit 180e2c7878
2 changed files with 31 additions and 0 deletions

View File

@ -55,6 +55,19 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
throw new \InvalidArgumentException('GuardAuthenticationProvider only supports NonAuthenticatedGuardToken');
}
if (!$token instanceof PreAuthenticationGuardToken) {
/*
* The listener *only* passes PreAuthenticationGuardToken instances.
* This means that an authenticated token (e.g. PostAuthenticationGuardToken)
* is being passed here, which happens if that token becomes
* "not authenticated" (e.g. happens if the user changes between
* requests). In this case, the user should be logged out, so
* we will return an AnonymousToken to accomplish that.
*/
return new AnonymousToken($this->providerKey, 'anon.');
}
// find the *one* GuardAuthenticator that this token originated from
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
// get a key that's unique to *this* guard authenticator

View File

@ -11,7 +11,9 @@
namespace Symfony\Component\Security\Guard\Tests\Provider;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProvider;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
/**
* @author Ryan Weaver <weaverryan@gmail.com>
@ -75,6 +77,22 @@ class GuardAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
$this->assertSame($authedToken, $actualAuthedToken);
}
public function testGuardWithNoLongerAuthenticatedTriggersLogout()
{
$providerKey = 'my_firewall_abc';
// create a token and mark it as NOT authenticated anymore
// this mimics what would happen if a user "changed" between request
$mockedUser = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
$token = new PostAuthenticationGuardToken($mockedUser, $providerKey, array('ROLE_USER'));
$token->setAuthenticated(false);
$provider = new GuardAuthenticationProvider(array(), $this->userProvider, $providerKey, $this->userChecker);
$actualToken = $provider->authenticate($token);
// this should return the anonymous user
$this->assertEquals(new AnonymousToken($providerKey, 'anon.'), $actualToken);
}
protected function setUp()
{
$this->userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');