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

Adding an event informing system that Email AuthCode has been validated #245

Open
wants to merge 3 commits 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
1 change: 1 addition & 0 deletions src/bundle/Resources/config/two_factor_provider_email.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
->args([
service('scheb_two_factor.security.email.code_generator'),
service('scheb_two_factor.security.email.form_renderer'),
service('event_dispatcher'),
])

->alias(CodeGeneratorInterface::class, 'scheb_two_factor.security.email.code_generator')
Expand Down
13 changes: 13 additions & 0 deletions src/email/Security/TwoFactor/Event/EmailCodeValidated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Scheb\TwoFactorBundle\Security\TwoFactor\Event;

readonly class EmailCodeValidated
{
public function __construct(
public string $email,
) {
}
}
14 changes: 14 additions & 0 deletions src/email/Security/TwoFactor/Event/EmailTwoFactorEvents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Scheb\TwoFactorBundle\Security\TwoFactor\Event;

class EmailTwoFactorEvents
{
public const EMAIL_CODE_VALIDATED = 'scheb_two_factor.email_code.validated';

private function __construct()
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\AuthenticationContextInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailCodeValidated;
use Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailTwoFactorEvents;
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Email\Generator\CodeGeneratorInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\TwoFactorFormRendererInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\TwoFactorProviderInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use function str_replace;

/**
Expand All @@ -19,6 +22,7 @@ class EmailTwoFactorProvider implements TwoFactorProviderInterface
public function __construct(
private readonly CodeGeneratorInterface $codeGenerator,
private readonly TwoFactorFormRendererInterface $formRenderer,
private readonly EventDispatcherInterface $eventDispatcher,
) {
}

Expand Down Expand Up @@ -48,7 +52,15 @@ public function validateAuthenticationCode(object $user, string $authenticationC
// Strip any user added spaces
$authenticationCode = str_replace(' ', '', $authenticationCode);

return $user->getEmailAuthCode() === $authenticationCode;
$isCodeValid = $user->getEmailAuthCode() === $authenticationCode;

if (false === $isCodeValid) {
return false;
}

$this->eventDispatcher->dispatch(new EmailCodeValidated($user->getEmailAuthRecipient()), EmailTwoFactorEvents::EMAIL_CODE_VALIDATED);

return true;
}

public function getFormRenderer(): TwoFactorFormRendererInterface
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Scheb\TwoFactorBundle\Tests\TestCase;
use stdClass;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class EmailTwoFactorProviderTest extends TestCase
{
Expand All @@ -22,11 +23,14 @@ class EmailTwoFactorProviderTest extends TestCase
private MockObject|CodeGeneratorInterface $generator;
private EmailTwoFactorProvider $provider;

private MockObject|EventDispatcherInterface $eventDispatcher;

protected function setUp(): void
{
$this->generator = $this->createMock(CodeGeneratorInterface::class);
$formRenderer = $this->createMock(TwoFactorFormRendererInterface::class);
$this->provider = new EmailTwoFactorProvider($this->generator, $formRenderer);
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
$this->provider = new EmailTwoFactorProvider($this->generator, $formRenderer, $this->eventDispatcher);
}

private function createUser(bool $emailAuthEnabled = true): MockObject|UserWithTwoFactorInterface
Expand Down Expand Up @@ -55,6 +59,20 @@ private function createAuthenticationContext(UserInterface|null $user = null): M
return $authContext;
}

private function expectEmailValidatedEventDispatched(): void
{
$this->eventDispatcher
->expects($this->once())
->method('dispatch');
}

private function expectEmailValidatedEventNotDispatched(): void
{
$this->eventDispatcher
->expects($this->never())
->method('dispatch');
}

/**
* @test
*/
Expand Down Expand Up @@ -128,6 +146,8 @@ public function prepareAuthentication_interfaceImplemented_codeGenerated(): void
public function validateAuthenticationCode_noTwoFactorUser_returnFalse(): void
{
$user = new stdClass();

$this->expectEmailValidatedEventNotDispatched();
$returnValue = $this->provider->validateAuthenticationCode($user, 'code');
$this->assertFalse($returnValue);
}
Expand All @@ -138,6 +158,8 @@ public function validateAuthenticationCode_noTwoFactorUser_returnFalse(): void
public function validateAuthenticationCode_validCodeGiven_returnTrue(): void
{
$user = $this->createUser();

$this->expectEmailValidatedEventDispatched();
$returnValue = $this->provider->validateAuthenticationCode($user, self::VALID_AUTH_CODE);
$this->assertTrue($returnValue);
}
Expand All @@ -148,6 +170,8 @@ public function validateAuthenticationCode_validCodeGiven_returnTrue(): void
public function validateAuthenticationCode_validCodeWithSpaces_returnTrue(): void
{
$user = $this->createUser();

$this->expectEmailValidatedEventDispatched();
$returnValue = $this->provider->validateAuthenticationCode($user, self::VALID_AUTH_CODE_WITH_SPACES);
$this->assertTrue($returnValue);
}
Expand All @@ -158,6 +182,8 @@ public function validateAuthenticationCode_validCodeWithSpaces_returnTrue(): voi
public function validateAuthenticationCode_validCodeGiven_returnFalse(): void
{
$user = $this->createUser();

$this->expectEmailValidatedEventNotDispatched();
$returnValue = $this->provider->validateAuthenticationCode($user, self::INVALID_AUTH_CODE);
$this->assertFalse($returnValue);
}
Expand Down
Loading