Skip to content

Commit

Permalink
Added config option for custom OTP window (#385)
Browse files Browse the repository at this point in the history
* Added config option for custom OTP window

* StyleCI fixes
  • Loading branch information
robtesch authored May 5, 2022
1 parent 9c67c3f commit 0b8e7a8
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/TwoFactorAuthenticationProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ public function qrCodeUrl($companyName, $companyEmail, $secret)
*/
public function verify($secret, $code)
{
if (is_int($customWindow = config('fortify-options.two-factor-authentication.window'))) {
$this->engine->setWindow($customWindow);
}

$timestamp = $this->engine->verifyKeyNewer(
$secret, $code, optional($this->cache)->get($key = 'fortify.2fa_codes.'.md5($code))
);
Expand Down
1 change: 1 addition & 0 deletions stubs/fortify.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
Features::twoFactorAuthentication([
'confirm' => true,
'confirmPassword' => true,
// 'window' => 0,
]),
],

Expand Down
35 changes: 35 additions & 0 deletions tests/AuthenticatedSessionControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,41 @@ public function test_two_factor_challenge_can_be_passed_via_code()
->assertSessionMissing('login.id');
}

public function test_two_factor_challenge_fails_for_old_otp_and_zero_window()
{
app('config')->set('auth.providers.users.model', TestTwoFactorAuthenticationSessionUser::class);

//Setting window to 0 should mean any old OTP is instantly invalid
app('config')->set('fortify.features', [
Features::twoFactorAuthentication(['window' => 0]),
]);

$this->loadLaravelMigrations(['--database' => 'testbench']);
$this->artisan('migrate', ['--database' => 'testbench'])->run();

$tfaEngine = app(Google2FA::class);
$userSecret = $tfaEngine->generateSecretKey();
$currentTs = $tfaEngine->getTimestamp();
$previousOtp = $tfaEngine->oathTotp($userSecret, $currentTs - 1);

$user = TestTwoFactorAuthenticationSessionUser::forceCreate([
'name' => 'Taylor Otwell',
'email' => '[email protected]',
'password' => bcrypt('secret'),
'two_factor_secret' => encrypt($userSecret),
]);

$response = $this->withSession([
'login.id' => $user->id,
'login.remember' => false,
])->withoutExceptionHandling()->post('/two-factor-challenge', [
'code' => $previousOtp,
]);

$response->assertRedirect('/two-factor-challenge')
->assertSessionHas('login.id');
}

public function test_two_factor_challenge_can_be_passed_via_recovery_code()
{
app('config')->set('auth.providers.users.model', TestTwoFactorAuthenticationSessionUser::class);
Expand Down

0 comments on commit 0b8e7a8

Please sign in to comment.