8000 bug #46760 Fix double authentication via RememberMe resulting in wron… · symfony/symfony@a390266 · GitHub
[go: up one dir, main page]

Skip to content

Commit a390266

Browse files
committed
bug #46760 Fix double authentication via RememberMe resulting in wrong RememberMe cookie being set in client (heiglandreas)
This PR was submitted for the 6.0 branch but it was squashed and merged into the 5.4 branch instead. Discussion ---------- Fix double authentication via RememberMe resulting in wrong RememberMe cookie being set in client | Q | A | ------------- | --- | Branch? | 6.0 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | There has not yet an issue opened for this. | License | MIT | Doc PR | n.a. In the RememberMe feature we have noticed that with a custom tokenVerifier it is possible to verify an old token. That works as expected but leads to the problematic issue that it will still result in the old token being integrated into the cookie that is sent back to the client. So the flow is as follows: * Customer sends a request "A" with `rem`-cookie with token "tokenA" * The user is authenticated via the token "tokenA", the token is refreshed with "tokenB". * Customer sends a request "B" with `rem`-cookie with token "tokenA" * Set-Cookie is sent back to the customer in response to request "A" with Remember-Me token "tokenB" * The user is authenticated via the token "tokenA" via a custom verifier. The last token was created less than 60 seconds ago, so let's not refresh the token but resend the current token. * Set-Cookie is sent back to the customer in response to request "B" with Remember-Me token "tokenA" * Remember-Me token "tokenA" overwrites the previously received token "tokenB" in the client. * Customer sends a request "C" with `rem`-cookie with "tokenA" * The user is not authenticated any more as the custom.verifier no longer accepts old token "tokenA" and "tokenA" doesn't match the persisted token "tokenB". The `rem`-cookie is overwritten with `deleted`. This PR will pass the persisted token (in the example "tokenB") in request "B" instead of the provided token (in the example "tokenA") and therefore not causing an overwrite of the Remember-Me cookie with a wrong value and a continuing functionality also when authentication-requests are sent within one minute of one another. How that can happen? By using double clicks for example in certain setups where then two authenticating requests are sent right after one another... Commits ------- 4dff49f Fix double authentication via RememberMe resulting in wrong RememberMe cookie being set in client
2 parents a01ce80 + 4dff49f commit a390266

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/Symfony/Component/Security/Http/RememberMe/PersistentRememberMeHandler.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public function processRememberMe(RememberMeDetails $rememberMeDetails, UserInte
7575

7676
if ($this->tokenVerifier) {
7777
$isTokenValid = $this->tokenVerifier->verifyToken($persistentToken, $tokenValue);
78+
$tokenValue = $persistentToken->getTokenValue();
7879
} else {
7980
$isTokenValid = hash_equals($persistentToken->getTokenValue(), $tokenValue);
8081
}

src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentRememberMeHandlerTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\HttpFoundation\RequestStack;
1818
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
1919
use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
20+
use Symfony\Component\Security\Core\Authenticatio 10000 n\RememberMe\TokenVerifierInterface;
2021
use Symfony\Component\Security\Core\Exception\AuthenticationException;
2122
use Symfony\Component\Security\Core\Exception\CookieTheftException;
2223
use Symfony\Component\Security\Core\User\InMemoryUser;
@@ -102,6 +103,42 @@ public function testConsumeRememberMeCookieValid()
102103
$this->assertSame(explode(':', $rememberParts[3])[0], explode(':', $cookieParts[3])[0]); // series
103104
}
104105

106+
public function testConsumeRememberMeCookieValidByValidatorWithoutUpdate()
107+
{
108+
$verifier = $this->createMock(TokenVerifierInterface::class);
109+
$handler = new PersistentRememberMeHandler($this->tokenProvider, 'secret', $this->userProvider, $this->requestStack, [], null, $verifier);
110+
111+
$persistentToken = new PersistentToken(InMemoryUser::class, 'wouter', 'series1', 'tokenvalue', new \DateTime('30 seconds'));
112+
113+
$this->tokenProvider->expects($this->any())
114+
->method('loadTokenBySeries')
115+
->with('series1')
116+
->willReturn($persistentToken)
117+
;
118+
119+
$verifier->expects($this->any())
120+
->method('verifyToken')
121+
->with($persistentToken, 'oldTokenValue')
122+
->willReturn(true)
123+
;
124+
125+
$rememberMeDetails = new RememberMeDetails(InMemoryUser::class, 'wouter', 360, 'series1:oldTokenValue');
126+
$handler->consumeRememberMeCookie($rememberMeDetails);
127+
128+
// assert that the cookie has been updated with a new base64 encoded token value
129+
$this->assertTrue($this->request->attributes->has(ResponseListener::COOKIE_ATTR_NAME));
130+
131+
/** @var Cookie $cookie */
132+
$cookie = $this->request->attributes->get(ResponseListener::COOKIE_ATTR_NAME);
133+
134+
$cookieParts = explode(':', base64_decode($cookie->getValue()), 4);
135+
136+
$this->assertSame(InMemoryUser::class, $cookieParts[0]); // class
137+
$this->assertSame(base64_encode('wouter'), $cookieParts[1]); // identifier
138+
$this->assertSame('360', $cookieParts[2]); // expire
139+
$this->assertSame('series1:tokenvalue', $cookieParts[3]); // value
140+
}
141+
105142
public function testConsumeRememberMeCookieInvalidToken()
106143
{
107144
$this->expectException(CookieTheftException::class);

0 commit comments

Comments
 (0)
0