Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat / Creation of BackupCodeUsedEvent #252

Open
wants to merge 1 commit into
base: 7.x
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions doc/events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorAuthenticati

Is dispatched when two-factor authentication is attempted, right before checking the code.

``scheb_two_factor.authentication.backup_code_used``
-------------------------------------------

Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorAuthenticationEvents::BACKUP_CODE_USED``

Is dispatched when two-factor authentication was successful with a backup-code.

``scheb_two_factor.authentication.success``
-------------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

namespace Scheb\TwoFactorBundle\Security\Http\EventListener;

use Scheb\TwoFactorBundle\Security\Authentication\Token\TwoFactorTokenInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Backup\BackupCodeManagerInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorAuthenticationEvent;
use Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorAuthenticationEvents;
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\PreparationRecorderInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
* @final
Expand All @@ -20,6 +26,9 @@ class CheckBackupCodeListener extends AbstractCheckCodeListener
public function __construct(
PreparationRecorderInterface $preparationRecorder,
private readonly BackupCodeManagerInterface $backupCodeManager,
private readonly TokenStorageInterface $tokenStorage,
private readonly RequestStack $requestStack,
private readonly EventDispatcherInterface $eventDispatcher,
) {
parent::__construct($preparationRecorder);
}
Expand All @@ -28,6 +37,16 @@ protected function isValidCode(string $providerName, object $user, string $code)
{
if ($this->backupCodeManager->isBackupCode($user, $code)) {
$this->backupCodeManager->invalidateBackupCode($user, $code);
$token = $this->tokenStorage->getToken();
if (!($token instanceof TwoFactorTokenInterface)) {
return false;
}

$request = $this->requestStack->getCurrentRequest();
if ($request) {
$event = new TwoFactorAuthenticationEvent($request, $token);
$this->eventDispatcher->dispatch($event, TwoFactorAuthenticationEvents::BACKUP_CODE_USED);
}

return true;
}
Expand Down
3 changes: 3 additions & 0 deletions src/bundle/Resources/config/backup_codes.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@
->args([
service('scheb_two_factor.provider_preparation_recorder'),
service('scheb_two_factor.backup_code_manager'),
service('security.token_storage'),
service('request_stack'),
service('event_dispatcher'),
]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class TwoFactorAuthenticationEvents
*/
public const ATTEMPT = 'scheb_two_factor.authentication.attempt';

/**
* When a backup-code is used.
*/
public const BACKUP_CODE_USED = 'scheb_two_factor.authentication.backup_code_used';

/**
* When two-factor authentication was successful (code was valid) for a single provider.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@
use PHPUnit\Framework\MockObject\MockObject;
use Scheb\TwoFactorBundle\Security\Http\EventListener\CheckBackupCodeListener;
use Scheb\TwoFactorBundle\Security\TwoFactor\Backup\BackupCodeManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
* @property CheckBackupCodeListener $listener
*/
class CheckBackupCodeListenerTest extends AbstractCheckCodeListenerTestSetup
{
private MockObject|BackupCodeManagerInterface $backupCodeManager;
private MockObject|TokenStorageInterface $tokenStorage;
private MockObject|RequestStack $requestStack;
private MockObject|EventDispatcherInterface $eventDispatcher;

protected function setUp(): void
{
parent::setUp();

$this->backupCodeManager = $this->createMock(BackupCodeManagerInterface::class);
$this->listener = new CheckBackupCodeListener($this->preparationRecorder, $this->backupCodeManager);
$this->tokenStorage = $this->createMock(TokenStorageInterface::class);
$this->requestStack = $this->createMock(RequestStack::class);
$this->eventDispatecher = $this->createMock(EventDispatcherInterface::class);
$this->listener = new CheckBackupCodeListener($this->preparationRecorder, $this->backupCodeManager, $this->tokenStorage, $this->requestStack, $this->eventDispatecher);
}

protected function expectDoNothing(): void
Expand Down
Loading