From 7a82b0c7366c03ec3420c1969b6e4ffb0b07a3de Mon Sep 17 00:00:00 2001 From: Jesse Rushlow Date: Thu, 16 May 2024 18:35:59 -0400 Subject: [PATCH] refactor token generator unit test --- .../ResetPasswordTokenGeneratorTest.php | 124 +++++++----------- 1 file changed, 51 insertions(+), 73 deletions(-) diff --git a/tests/Unit/Generator/ResetPasswordTokenGeneratorTest.php b/tests/Unit/Generator/ResetPasswordTokenGeneratorTest.php index 462d4838..95de1fab 100644 --- a/tests/Unit/Generator/ResetPasswordTokenGeneratorTest.php +++ b/tests/Unit/Generator/ResetPasswordTokenGeneratorTest.php @@ -20,93 +20,71 @@ */ class ResetPasswordTokenGeneratorTest extends TestCase { - /** - * @var MockObject|ResetPasswordRandomGenerator - */ - private $mockRandomGenerator; - - /** - * @var MockObject|\DateTimeImmutable - */ - private $mockExpiresAt; + private MockObject&\DateTimeImmutable $mockExpiresAt; + private ResetPasswordTokenGenerator $tokenGenerator; protected function setUp(): void { - $this->mockRandomGenerator = $this->createMock(ResetPasswordRandomGenerator::class); $this->mockExpiresAt = $this->createMock(\DateTimeImmutable::class); + $this->tokenGenerator = new ResetPasswordTokenGenerator('secret-key', new ResetPasswordRandomGenerator()); } - public function testSelectorGeneratedByRandomGenerator(): void + public function testCreateTokenReturnsValidHashedTokenComponents(): void { - $this->mockRandomGenerator - ->expects($this->exactly(2)) - ->method('getRandomAlphaNumStr') - ; + $result = $this->tokenGenerator->createToken($this->mockExpiresAt, 'userId'); - $generator = $this->getTokenGenerator(); - $generator->createToken($this->mockExpiresAt, 'userId'); - } + // The public token = "selector token" + "verifier token" + self::assertSame(20, \strlen($result->getSelector())); + self::assertSame(40, \strlen($result->getPublicToken())); - public function testHashedTokenIsCreatedWithExpectedParams(): void - { - $this->mockRandomGenerator - ->expects($this->exactly(2)) - ->method('getRandomAlphaNumStr') - ->willReturnOnConsecutiveCalls('verifier', 'selector') - ; - - $this->mockExpiresAt - ->expects($this->once()) - ->method('getTimestamp') - ->willReturn(2020) - ; - - $expected = hash_hmac( - 'sha256', - json_encode(['verifier', 'user1234', 2020]), - 'key', - true - ); - - $generator = $this->getTokenGenerator(); - $result = $generator->createToken($this->mockExpiresAt, 'user1234'); - - self::assertSame(base64_encode($expected), $result->getHashedToken()); + $verifier = substr($result->getPublicToken(), 20, 20); + + $expectedHash = base64_encode(hash_hmac( + algo: 'sha256', + data: json_encode([$verifier, 'userId', $this->mockExpiresAt->getTimestamp()]), + key: 'secret-key', + binary: true + )); + + self::assertSame($expectedHash, $result->getHashedToken()); } - public function testHashedTokenIsCreatedUsingOptionVerifierParam(): void + public function testCreateTokenUsesProvidedVerifierToken(): void { - $date = 2020; - $userId = 'user1234'; - $knownVerifier = 'verified'; - - $this->mockRandomGenerator - ->expects($this->once()) - ->method('getRandomAlphaNumStr') - ->willReturnOnConsecutiveCalls('un-used-verifier', 'selector') - ; - - $this->mockExpiresAt - ->expects($this->once()) - ->method('getTimestamp') - ->willReturn($date) - ; - - $knownToken = hash_hmac( - 'sha256', - json_encode([$knownVerifier, $userId, $date]), - 'key', - true - ); - - $generator = $this->getTokenGenerator(); - $result = $generator->createToken($this->mockExpiresAt, $userId, $knownVerifier); - - self::assertSame(base64_encode($knownToken), $result->getHashedToken()); + $result = $this->tokenGenerator->createToken($this->mockExpiresAt, 'userId', '1234'); + + $expectedHash = base64_encode(hash_hmac( + algo: 'sha256', + data: json_encode(['1234', 'userId', $this->mockExpiresAt->getTimestamp()]), + key: 'secret-key', + binary: true + )); + + self::assertSame($expectedHash, $result->getHashedToken()); } - private function getTokenGenerator(): ResetPasswordTokenGenerator + public function testCreateTokenUsesProvidedParams(): void { - return new ResetPasswordTokenGenerator('key', $this->mockRandomGenerator); + $result = $this->tokenGenerator->createToken($this->mockExpiresAt, 'userId', '1234'); + + $expectedHash = base64_encode(hash_hmac( + algo: 'sha256', + data: json_encode(['1234', 'userId', '0123456789']), + key: 'secret-key', + binary: true + )); + + // We used a "fake" timestamp in our expectedHash + self::assertNotSame($expectedHash, $result->getHashedToken()); + + $expectedHash = base64_encode(hash_hmac( + algo: 'sha256', + data: json_encode(['1234', 'bad-user-id', $this->mockExpiresAt->getTimestamp()]), + key: 'secret-key', + binary: true + )); + + // We used a "fake" user id in our expectedHash + self::assertNotSame($expectedHash, $result->getHashedToken()); } }