diff --git a/src/Handler/LogoutHandler.php b/src/Handler/LogoutHandler.php index 15bdc35..c07dd6b 100644 --- a/src/Handler/LogoutHandler.php +++ b/src/Handler/LogoutHandler.php @@ -12,6 +12,7 @@ use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManager; use Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; @@ -30,9 +31,10 @@ public function __construct(TokenStorageInterface $tokenStorage, ManagerRegistry /** * Invalidate the current login by invalidating the current JWT token. */ - public function __invoke(Logout $logout): void + public function __invoke(Logout $logout): Response { $token = $this->tokenStorage->getToken(); + $response = new Response(); if ($token instanceof JWTUserToken) { $invalidToken = new InvalidToken(); @@ -46,6 +48,11 @@ public function __invoke(Logout $logout): void } else { throw new \RuntimeException('Unable to invalid token because doctrine is not set up correctly. Please configure `vendor/connectholland/secure-jwt/src/Entity` as an annotated entity path (see README.md for more details)'); } + + $response->headers->clearCookie('BEARER', '/', null, true, true, 'none'); + } + + return $response; } } diff --git a/src/Security/Http/Authentication/AuthenticationSuccessHandler.php b/src/Security/Http/Authentication/AuthenticationSuccessHandler.php index ffcc8ce..1a14f10 100644 --- a/src/Security/Http/Authentication/AuthenticationSuccessHandler.php +++ b/src/Security/Http/Authentication/AuthenticationSuccessHandler.php @@ -45,7 +45,7 @@ public function handleAuthenticationSuccess(UserInterface $user, $jwt = null): J $decoded = $this->jwtEncoder->decode($data['token']); $this->responsePayload = array_merge($this->responsePayload, $decoded); $response = new JsonResponse(['result' => 'ok', 'payload' => $this->responsePayload]); - $response->headers->setCookie(new Cookie('BEARER', $data['token'], 0, '/', null, true, true, false, $this->sameSite)); + $response->headers->setCookie(new Cookie('BEARER', $data['token'], $decoded['exp'], '/', null, true, true, false, $this->sameSite)); return $response; } diff --git a/tests/Handler/LogoutHandlerTest.php b/tests/Handler/LogoutHandlerTest.php index b731364..1f06e80 100644 --- a/tests/Handler/LogoutHandlerTest.php +++ b/tests/Handler/LogoutHandlerTest.php @@ -14,6 +14,7 @@ use Doctrine\ORM\EntityManager; use Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; @@ -45,6 +46,26 @@ public function testOnlyHandleJWTTokens(): void $this->handler->__invoke(new Logout()); } + public function testRemovesCookie(): void + { + $this->tokenStorage->setToken(new JWTUserToken([], null, 'unit-test-token')); + $manager = $this->createMock(EntityManager::class); + + $this->doctrine + ->expects($this->once()) + ->method('getManagerForClass') + ->willReturn($manager); + + $response = $this->handler->__invoke(new Logout()); + $this->assertInstanceOf(Response::class, $response); + $cookies = $response->headers->getCookies(); + + $this->assertCount(1, $cookies); + $this->assertSame('BEARER', $cookies[0]->getName()); + $this->assertSame(1, $cookies[0]->getExpiresTime()); + } + + public function testPersistsInvalidToken(): void { $this->tokenStorage->setToken(new JWTUserToken([], null, 'unit-test-token')); diff --git a/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php b/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php index 55362fb..c96971b 100644 --- a/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php +++ b/tests/Security/Http/Authentication/AuthenticationSuccessHandlerTest.php @@ -45,6 +45,7 @@ public function testOnAuthenticationSuccess(): void $this->assertSame('example@example.org', $content['payload']['user']); $this->assertCount(1, $cookies); $this->assertSame('secrettoken', $cookies[0]->getValue()); + $this->assertSame(1627902433, $cookies[0]->getExpiresTime()); } public function testHandleAuthenticationSuccess() @@ -94,7 +95,7 @@ private function getEncoder(): JWTEncoderInterface $encoder ->expects($this->once()) ->method('decode') - ->willReturn(['user' => 'example@example.org']); + ->willReturn(['user' => 'example@example.org', 'exp' => 1627902433]); return $encoder; }