Skip to content

Commit 621b6a4

Browse files
committed
OXDEV-9078 Implement challenge trigger method
1 parent f2b078b commit 621b6a4

4 files changed

Lines changed: 68 additions & 1 deletion

File tree

src/Authentication/TwoFactorAuth/OTP/OtpFacade.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,23 @@
99

1010
namespace OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP;
1111

12+
use OxidEsales\Eshop\Core\Utils;
13+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Notifier\Factory\OtpNotifierFactoryInterface;
1214
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpChallengeStateServiceInterface;
15+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeGeneratorServiceInterface;
1316
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeValidatorServiceInterface;
17+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Settings\TwoFASettingsInterface;
1418
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAServiceInterface;
1519

1620
class OtpFacade implements TwoFAServiceInterface
1721
{
1822
public function __construct(
1923
private OtpChallengeStateServiceInterface $stateService,
2024
private OtpCodeValidatorServiceInterface $codeValidator,
25+
private OtpCodeGeneratorServiceInterface $codeGenerator,
26+
private OtpNotifierFactoryInterface $notifierFactory,
27+
private TwoFASettingsInterface $settings,
28+
private Utils $utils,
2129
) {
2230
}
2331

@@ -34,7 +42,12 @@ public function isVerified(string $userId): bool
3442

3543
public function triggerChallenge(string $userId): void
3644
{
37-
// todo-critical: implement
45+
$code = $this->codeGenerator->generateCode();
46+
47+
$this->stateService->createChallengeState($userId, $code);
48+
$this->notifierFactory->create($userId)->notify($userId, $code);
49+
50+
$this->utils->redirect($this->settings->getVerificationUrl());
3851
}
3952

4053
public function invalidateChallenge(string $userId): void

src/Authentication/TwoFactorAuth/OTP/services.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ services:
77
_defaults:
88
autowire: true
99
public: false
10+
bind:
11+
OxidEsales\Eshop\Core\Utils: '@=service("OxidEsales\\SecurityModule\\Core\\Registry").getUtils()'
1012

1113
OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\OtpFacade: ~

src/Authentication/TwoFactorAuth/services.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ imports:
44
- { resource: Transput/services.yaml }
55
- { resource: Controller/services.yaml }
66
- { resource: Factory/services.yaml }
7+
- { resource: Settings/services.yaml }
78
- { resource: OTP/services.yaml }

tests/Unit/Authentication/TwoFactorAuth/OTP/OtpFacadeTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
namespace OxidEsales\SecurityModule\Tests\Unit\Authentication\TwoFactorAuth\OTP;
1111

1212
use DateTimeImmutable;
13+
use OxidEsales\Eshop\Core\Utils;
14+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Notifier\Factory\OtpNotifierFactoryInterface;
15+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Notifier\OtpNotifierInterface;
1316
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\OtpFacade;
1417
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpChallengeStateServiceInterface;
18+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeGeneratorServiceInterface;
1519
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeValidatorServiceInterface;
20+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Settings\TwoFASettingsInterface;
1621
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\DTO\OtpChallengeStateInterface;
1722
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAServiceInterface;
1823
use PHPUnit\Framework\Attributes\Test;
@@ -113,13 +118,59 @@ public function verifyTriggersCodeValidator(): void
113118
$sut->verify(userId: $userId, code: $code);
114119
}
115120

121+
#[Test]
122+
public function triggerChallengeGeneratesCodeCreatesStateAndNotifies(): void
123+
{
124+
$codeGeneratorStub = $this->createStub(OtpCodeGeneratorServiceInterface::class);
125+
$codeGeneratorStub->method('generateCode')->willReturn($code = uniqid());
126+
127+
$stateServiceSpy = $this->createMock(OtpChallengeStateServiceInterface::class);
128+
$stateServiceSpy->expects($this->once())
129+
->method('createChallengeState')
130+
->with($userId = uniqid(), $code);
131+
132+
$notifierSpy = $this->createMock(OtpNotifierInterface::class);
133+
$notifierSpy->expects($this->once())
134+
->method('notify')
135+
->with($userId, $code);
136+
137+
$notifierFactoryStub = $this->createStub(OtpNotifierFactoryInterface::class);
138+
$notifierFactoryStub->method('create')->willReturn($notifierSpy);
139+
140+
$settingsStub = $this->createStub(TwoFASettingsInterface::class);
141+
$settingsStub->method('getVerificationUrl')->willReturn($verificationUrl = uniqid());
142+
143+
$utilsSpy = $this->createMock(Utils::class);
144+
$utilsSpy->expects($this->once())
145+
->method('redirect')
146+
->with($verificationUrl);
147+
148+
$sut = $this->getSut(
149+
stateService: $stateServiceSpy,
150+
codeGenerator: $codeGeneratorStub,
151+
notifierFactory: $notifierFactoryStub,
152+
settings: $settingsStub,
153+
utils: $utilsSpy,
154+
);
155+
156+
$sut->triggerChallenge(userId: $userId);
157+
}
158+
116159
private function getSut(
117160
OtpChallengeStateServiceInterface $stateService = null,
118161
OtpCodeValidatorServiceInterface $codeValidator = null,
162+
OtpCodeGeneratorServiceInterface $codeGenerator = null,
163+
OtpNotifierFactoryInterface $notifierFactory = null,
164+
TwoFASettingsInterface $settings = null,
165+
Utils $utils = null,
119166
): OtpFacade {
120167
return new OtpFacade(
121168
stateService: $stateService ?? $this->createStub(OtpChallengeStateServiceInterface::class),
122169
codeValidator: $codeValidator ?? $this->createStub(OtpCodeValidatorServiceInterface::class),
170+
codeGenerator: $codeGenerator ?? $this->createStub(OtpCodeGeneratorServiceInterface::class),
171+
notifierFactory: $notifierFactory ?? $this->createStub(OtpNotifierFactoryInterface::class),
172+
settings: $settings ?? $this->createStub(TwoFASettingsInterface::class),
173+
utils: $utils ?? $this->createStub(Utils::class),
123174
);
124175
}
125176
}

0 commit comments

Comments
 (0)