Skip to content

Commit b34813a

Browse files
committed
Dispatch events when authentication providers process codes, #245
1 parent e324d7e commit b34813a

File tree

16 files changed

+385
-10
lines changed

16 files changed

+385
-10
lines changed

doc/events.rst

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,111 @@ Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\BackupCodeEvents::INV
9898
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
9999

100100
Is dispatched when the code was deemed to be a invalid backup code.
101+
102+
103+
Email Authentication Events
104+
---------------------------
105+
106+
The following events are dispatched when the email code authentication provider is used:
107+
108+
``scheb_two_factor.provider.email.sent``
109+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110+
111+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailCodeEvents::SENT``
112+
113+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
114+
115+
Is dispatched whenever a code was sent via email to the user.
116+
117+
``scheb_two_factor.provider.email.check``
118+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
119+
120+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailCodeEvents::CHECK``
121+
122+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
123+
124+
Is dispatched whenever a code is checked if it is a valid email code.
125+
126+
``scheb_two_factor.provider.email.valid``
127+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128+
129+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailCodeEvents::VALID``
130+
131+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
132+
133+
Is dispatched when the code was deemed to be a valid email code.
134+
135+
``scheb_two_factor.provider.email.invalid``
136+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
137+
138+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailCodeEvents::INVALID``
139+
140+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
141+
142+
Is dispatched when the code was deemed to be a invalid email code.
143+
144+
145+
Google Authenticator Events
146+
---------------------------
147+
148+
The following events are dispatched when the Google Authenticator authentication provider is used:
149+
150+
``scheb_two_factor.provider.google.check``
151+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
152+
153+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\GoogleAuthenticatorCodeEvents::CHECK``
154+
155+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
156+
157+
Is dispatched whenever a code is checked if it is a valid Google Authenticator code.
158+
159+
``scheb_two_factor.provider.google.valid``
160+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161+
162+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\GoogleAuthenticatorCodeEvents::VALID``
163+
164+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
165+
166+
Is dispatched when the code was deemed to be a valid Google Authenticator code.
167+
168+
``scheb_two_factor.provider.google.invalid``
169+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
170+
171+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\GoogleAuthenticatorCodeEvents::INVALID``
172+
173+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
174+
175+
Is dispatched when the code was deemed to be a invalid Google Authenticator code.
176+
177+
178+
TOTP Authentication Events
179+
--------------------------
180+
181+
The following events are dispatched when the TOTP authentication provider is used:
182+
183+
``scheb_two_factor.provider.totp.check``
184+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
185+
186+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TotpCodeEvents::CHECK``
187+
188+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
189+
190+
Is dispatched whenever a code is checked if it is a valid TOTP code.
191+
192+
``scheb_two_factor.provider.totp.valid``
193+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
194+
195+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TotpCodeEvents::VALID``
196+
197+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
198+
199+
Is dispatched when the code was deemed to be a valid TOTP code.
200+
201+
``scheb_two_factor.provider.totp.invalid``
202+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203+
204+
Constant: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TotpCodeEvents::INVALID``
205+
206+
Event class: ``Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent``
207+
208+
Is dispatched when the code was deemed to be a invalid TOTP code.

doc/providers/email.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,8 @@ Then register it as a service and update your configuration:
273273
scheb_two_factor:
274274
email:
275275
form_renderer: acme.custom_form_renderer_service
276+
277+
Events
278+
------
279+
280+
See :doc:`Events </events>`

doc/providers/google.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,8 @@ An example how to render the QR code with ``endroid/qr-code`` version 4 can be f
227227

228228
**Security note:** Keep the QR code content within your application. Render the image yourself. Do not pass the
229229
content to an external service, because this is exposing the secret code to that service.
230+
231+
Events
232+
------
233+
234+
See :doc:`Events </events>`

doc/providers/totp.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,8 @@ An example how to render the QR code with ``endroid/qr-code`` version 4 can be f
243243

244244
**Security note:** Keep the QR code content within your application. Render the image yourself. Do not pass the
245245
content to an external service, because this is exposing the secret code to that service.
246+
247+
Events
248+
------
249+
250+
See :doc:`Events </events>`

src/bundle/Resources/config/two_factor_provider_email.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
->args([
4040
service('scheb_two_factor.security.email.code_generator'),
4141
service('scheb_two_factor.security.email.form_renderer'),
42+
service('event_dispatcher'),
4243
])
4344

4445
->alias(CodeGeneratorInterface::class, 'scheb_two_factor.security.email.code_generator')

src/bundle/Resources/config/two_factor_provider_google.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
->public()
2727
->args([
2828
service('scheb_two_factor.security.google_totp_factory'),
29+
service('event_dispatcher'),
2930
'%scheb_two_factor.google.leeway%',
3031
])
3132

src/bundle/Resources/config/two_factor_provider_totp.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
->public()
2828
->args([
2929
service('scheb_two_factor.security.totp_factory'),
30+
service('event_dispatcher'),
3031
'%scheb_two_factor.totp.leeway%',
3132
])
3233

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Scheb\TwoFactorBundle\Security\TwoFactor\Event;
6+
7+
/**
8+
* @final
9+
*/
10+
class EmailCodeEvents
11+
{
12+
/**
13+
* When a code was sent by the email provider.
14+
*/
15+
public const SENT = 'scheb_two_factor.provider.email.sent';
16+
17+
/**
18+
* When a code is about to be checked by the email provider.
19+
*/
20+
public const CHECK = 'scheb_two_factor.provider.email.check';
21+
22+
/**
23+
* When the code was deemed to be valid by the email provider.
24+
*/
25+
public const VALID = 'scheb_two_factor.provider.email.valid';
26+
27+
/**
28+
* When the code was deemed to be invalid by the email provider.
29+
*/
30+
public const INVALID = 'scheb_two_factor.provider.email.invalid';
31+
}

src/email/Security/TwoFactor/Provider/Email/EmailTwoFactorProvider.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66

77
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
88
use Scheb\TwoFactorBundle\Security\TwoFactor\AuthenticationContextInterface;
9+
use Scheb\TwoFactorBundle\Security\TwoFactor\Event\EmailCodeEvents;
10+
use Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorCodeEvent;
911
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Email\Generator\CodeGeneratorInterface;
1012
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\TwoFactorFormRendererInterface;
1113
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\TwoFactorProviderInterface;
14+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1215
use function str_replace;
1316

1417
/**
@@ -19,6 +22,7 @@ class EmailTwoFactorProvider implements TwoFactorProviderInterface
1922
public function __construct(
2023
private readonly CodeGeneratorInterface $codeGenerator,
2124
private readonly TwoFactorFormRendererInterface $formRenderer,
25+
private readonly EventDispatcherInterface $eventDispatcher,
2226
) {
2327
}
2428

@@ -37,6 +41,9 @@ public function prepareAuthentication(object $user): void
3741
}
3842

3943
$this->codeGenerator->generateAndSend($user);
44+
45+
$event = new TwoFactorCodeEvent($user, $user->getEmailAuthCode() ?? '');
46+
$this->eventDispatcher->dispatch($event, EmailCodeEvents::SENT);
4047
}
4148

4249
public function validateAuthenticationCode(object $user, string $authenticationCode): bool
@@ -45,10 +52,15 @@ public function validateAuthenticationCode(object $user, string $authenticationC
4552
return false;
4653
}
4754

55+
$event = new TwoFactorCodeEvent($user, $authenticationCode);
56+
$this->eventDispatcher->dispatch($event, EmailCodeEvents::CHECK);
57+
4858
// Strip any user added spaces
4959
$authenticationCode = str_replace(' ', '', $authenticationCode);
60+
$isValid = $user->getEmailAuthCode() === $authenticationCode;
61+
$this->eventDispatcher->dispatch($event, $isValid ? EmailCodeEvents::VALID : EmailCodeEvents::INVALID);
5062

51-
return $user->getEmailAuthCode() === $authenticationCode;
63+
return $isValid;
5264
}
5365

5466
public function getFormRenderer(): TwoFactorFormRendererInterface
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Scheb\TwoFactorBundle\Security\TwoFactor\Event;
6+
7+
/**
8+
* @final
9+
*/
10+
class GoogleAuthenticatorCodeEvents
11+
{
12+
/**
13+
* When a code is about to be checked by the Google Authenticator provider.
14+
*/
15+
public const CHECK = 'scheb_two_factor.provider.google.check';
16+
17+
/**
18+
* When the code was deemed to be valid by the Google Authenticator provider.
19+
*/
20+
public const VALID = 'scheb_two_factor.provider.google.valid';
21+
22+
/**
23+
* When the code was deemed to be invalid by the Google Authenticator provider.
24+
*/
25+
public const INVALID = 'scheb_two_factor.provider.google.invalid';
26+
}

0 commit comments

Comments
 (0)