Skip to content
This repository has been archived by the owner on Mar 28, 2022. It is now read-only.

Commit

Permalink
Fix refreshing token cookie overwriting expire cookie
Browse files Browse the repository at this point in the history
  • Loading branch information
DASPRiD committed Feb 14, 2017
1 parent ebb8d6a commit 4629c1b
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 21 deletions.
30 changes: 19 additions & 11 deletions src/CookieManager.php
Expand Up @@ -7,6 +7,7 @@
use DASPRiD\Helios\CurrentTime\SystemTimeProvider;
use DASPRiD\Helios\Exception\CookieNotFoundException;
use DASPRiD\Helios\Exception\InvalidTokenException;
use Dflydev\FigCookies\FigRequestCookies;
use Dflydev\FigCookies\FigResponseCookies;
use Dflydev\FigCookies\SetCookie;
use Lcobucci\JWT\Token;
Expand Down Expand Up @@ -54,11 +55,16 @@ public function __construct(
$this->currentTimeProvider = $currentTimeProvider ?: new SystemTimeProvider();
}

/**
* @param mixed $subject
*/
public function injectTokenCookie(ResponseInterface $response, $subject, bool $endAtSession) : ResponseInterface
{
public function injectTokenCookie(
ResponseInterface $response,
$subject,
bool $endAtSession,
bool $overwriteExpireCookie = true
) : ResponseInterface {
if (!$overwriteExpireCookie && '' === FigResponseCookies::get($response, $this->cookieName)->getValue()) {
return $response;
}

$currentTimestamp = $this->currentTimeProvider->getCurrentTime()->getTimestamp();
$setCookie = SetCookie::create($this->cookieName)
->withHttpOnly(true)
Expand Down Expand Up @@ -86,14 +92,15 @@ public function expireTokenCookie(ResponseInterface $response) : ResponseInterfa

public function hasValidToken(ServerRequestInterface $request) : bool
{
$cookies = $request->getCookieParams();
$requestCookie = FigRequestCookies::get($request, $this->cookieName);
$cookieValue = $requestCookie->getValue();

if (!array_key_exists($this->cookieName, $cookies)) {
if (null === $cookieValue) {
return false;
}

try {
$this->tokenManager->parseSignedToken($cookies[$this->cookieName]);
$this->tokenManager->parseSignedToken($cookieValue);
} catch (InvalidTokenException $e) {
return false;
}
Expand All @@ -103,12 +110,13 @@ public function hasValidToken(ServerRequestInterface $request) : bool

public function getToken(ServerRequestInterface $request) : Token
{
$cookies = $request->getCookieParams();
$requestCookie = FigRequestCookies::get($request, $this->cookieName);
$cookieValue = $requestCookie->getValue();

if (!array_key_exists($this->cookieName, $cookies)) {
if (null === $cookieValue) {
throw CookieNotFoundException::fromNonExistentCookie($this->cookieName);
}

return $this->tokenManager->parseSignedToken($cookies[$this->cookieName]);
return $this->tokenManager->parseSignedToken($cookieValue);
}
}
10 changes: 6 additions & 4 deletions src/CookieManagerInterface.php
Expand Up @@ -9,10 +9,12 @@

interface CookieManagerInterface
{
/**
* @param mixed $subject
*/
public function injectTokenCookie(ResponseInterface $response, $subject, bool $endAtSession) : ResponseInterface;
public function injectTokenCookie(
ResponseInterface $response,
$subject,
bool $endAtSession,
bool $overwriteExpireCookie = true
) : ResponseInterface;

public function expireTokenCookie(ResponseInterface $response) : ResponseInterface;

Expand Down
1 change: 1 addition & 0 deletions src/IdentityMiddleware.php
Expand Up @@ -77,6 +77,7 @@ public function __invoke(
return $this->cookieManager->injectTokenCookie(
$nextResponse,
$subject,
false,
false
);
}
Expand Down
49 changes: 44 additions & 5 deletions test/CookieManagerTest.php
Expand Up @@ -52,6 +52,45 @@ public function testInjectNonSecureTokenCookie()
], $newResponse->getHeader('Set-Cookie'));
}

public function testInjectTookenCookieExpiringEndOfSession()
{
$tokenManager = $this->prophesize(TokenManagerInterface::class);
$tokenManager->getSignedToken('foo', 100, true)->willReturn(new Token());
$cookieManager = $this->createCookieManager($tokenManager->reveal(), false);

$originalResponse = new EmptyResponse();
$newResponse = $cookieManager->injectTokenCookie(
$originalResponse,
'foo',
true
);

$this->assertSame([
'helios=..; Path=/; HttpOnly',
], $newResponse->getHeader('Set-Cookie'));
}

public function testExpireCookieIsNotOverwrittenWithSetFlag()
{
$tokenManager = $this->prophesize(TokenManagerInterface::class);
$tokenManager->getSignedToken('foo', 100, false)->willReturn(new Token());
$cookieManager = $this->createCookieManager($tokenManager->reveal(), false);

$originalResponse = new EmptyResponse();
$expireResponse = $cookieManager->expireTokenCookie($originalResponse);

$newResponse = $cookieManager->injectTokenCookie(
$expireResponse,
'foo',
false,
false
);

$this->assertSame([
'helios=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; HttpOnly',
], $newResponse->getHeader('Set-Cookie'));
}

public function testSecureExpireTokenCookie()
{
$cookieManager = $this->createCookieManager($this->prophesize(TokenManagerInterface::class)->reveal());
Expand Down Expand Up @@ -83,7 +122,7 @@ public function testHasValidTokenWithExistentValidToken()
$cookieManager = $this->createCookieManager($tokenManager->reveal());

$request = $this->prophesize(ServerRequestInterface::class);
$request->getCookieParams()->willReturn(['helios' => 'foo']);
$request->getHeaderLine('Cookie')->willReturn('helios=foo');

$this->assertTrue($cookieManager->hasValidToken($request->reveal()));
}
Expand All @@ -95,7 +134,7 @@ public function testHasValidTokenWithNonExistentToken()
$cookieManager = $this->createCookieManager($tokenManager->reveal());

$request = $this->prophesize(ServerRequestInterface::class);
$request->getCookieParams()->willReturn([]);
$request->getHeaderLine('Cookie')->willReturn('');

$this->assertFalse($cookieManager->hasValidToken($request->reveal()));
}
Expand All @@ -107,7 +146,7 @@ public function testHasValidTokenWithInvalidToken()
$cookieManager = $this->createCookieManager($tokenManager->reveal());

$request = $this->prophesize(ServerRequestInterface::class);
$request->getCookieParams()->willReturn(['helios' => 'foo']);
$request->getHeaderLine('Cookie')->willReturn('helios=foo');

$this->assertFalse($cookieManager->hasValidToken($request->reveal()));
}
Expand All @@ -120,7 +159,7 @@ public function testGetTokenWithExistentToken()
$cookieManager = $this->createCookieManager($tokenManager->reveal());

$request = $this->prophesize(ServerRequestInterface::class);
$request->getCookieParams()->willReturn(['helios' => 'foo']);
$request->getHeaderLine('Cookie')->willReturn('helios=foo');

$this->assertSame($token, $cookieManager->getToken($request->reveal()));
}
Expand All @@ -130,7 +169,7 @@ public function testGetTokenWithNonExistentToken()
$cookieManager = $this->createCookieManager($this->prophesize(TokenManagerInterface::class)->reveal());

$request = $this->prophesize(ServerRequestInterface::class);
$request->getCookieParams()->willReturn([]);
$request->getHeaderLine('Cookie')->willReturn('');

$this->expectException(CookieNotFoundException::class);
$this->expectExceptionMessage('Cookie with name "helios" was not found');
Expand Down
2 changes: 1 addition & 1 deletion test/IdentityMiddlewareTest.php
Expand Up @@ -185,7 +185,7 @@ public function testRefresh(array $claims, bool $expectRefresh)
] + $claims));

if ($expectRefresh) {
$cookieManager->injectTokenCookie($response, 'foo', false)->shouldBeCalled();
$cookieManager->injectTokenCookie($response, 'foo', false, false)->shouldBeCalled();
} else {
$cookieManager->injectTokenCookie()->shouldNotBeCalled();
}
Expand Down

0 comments on commit 4629c1b

Please sign in to comment.