Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/GoogleAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Writer\PngWriter;
use Exception;
use InvalidArgumentException;
use Vectorface\OtpAuth\Base32;
use Vectorface\OtpAuth\UriBuilder;

Expand Down Expand Up @@ -143,7 +144,7 @@ public function verifyCode(string $secret, string $code, int $discrepancy = 1) :
{
$currentTimeSlice = floor(time() / 30);

if (strlen($code) != 6) {
if (strlen($code) !== $this->_codeLength || !ctype_digit($code)) {
return false;
}

Expand All @@ -163,10 +164,15 @@ public function verifyCode(string $secret, string $code, int $discrepancy = 1) :
}

/**
* Set the code length, should be >=6
* Set the code length, must be between 6 and 8 (RFC 4226)
*
* @throws InvalidArgumentException
*/
public function setCodeLength(int $length) : self
{
if ($length < 6 || $length > 8) {
throw new InvalidArgumentException('Code length must be between 6 and 8');
}
$this->_codeLength = $length;
return $this;
}
Expand Down
51 changes: 51 additions & 0 deletions tests/GoogleAuthenticatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Tests\Vectorface;

use Exception;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use Vectorface\GoogleAuthenticator;
use Vectorface\OtpAuth\Parameters\Algorithm;
Expand Down Expand Up @@ -163,13 +164,63 @@ public function testVerifyCodeWithLeadingZero()
$this->assertEquals(false, $result);
}

/**
* @throws Exception
*/
public function testVerifyCodeWithEightDigits()
{
$secret = 'SECRET';
$ga = $this->googleAuthenticator->setCodeLength(8);

$code = $ga->getCode($secret);
$this->assertEquals(8, strlen($code));
$this->assertTrue($ga->verifyCode($secret, $code));

// A 6-digit code must not verify when 8 digits are configured
$this->assertFalse($ga->verifyCode($secret, substr($code, 0, 6)));
}

/**
* @throws Exception
*/
public function testVerifyCodeRejectsNonNumericCode()
{
$secret = 'SECRET';

$this->assertFalse($this->googleAuthenticator->verifyCode($secret, 'abcdef'));
$this->assertFalse($this->googleAuthenticator->verifyCode($secret, '12345x'));
$this->assertFalse($this->googleAuthenticator->verifyCode($secret, "12345\n"));
}

public function testSetCodeLength()
{
$result = $this->googleAuthenticator->setCodeLength(6);

$this->assertInstanceOf(GoogleAuthenticator::class, $result);
}

public function invalidCodeLengthProvider()
{
return [
'Too short' => [5],
'Too long' => [9],
'Zero' => [0],
'Negative' => [-1],
];
}

/**
* @dataProvider invalidCodeLengthProvider
* @param int $length
*/
public function testSetCodeLengthRejectsOutOfRangeValues(int $length)
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Code length must be between 6 and 8');

$this->googleAuthenticator->setCodeLength($length);
}

public function badSecretProvider()
{
return [
Expand Down
Loading