Passed
Pull Request — main (#308)
by Paul
16:16 queued 09:55
created

selfAssertedTokenRecoveryTokenSmsAuthentication()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 63
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 42
nc 8
nop 3
dl 0
loc 63
rs 7.6924
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types = 1);
4
5
/**
6
 * Copyright 2022 SURFnet B.V.
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
Coding Style introduced by
Missing @link tag in file comment
Loading history...
20
21
namespace Surfnet\StepupSelfService\SelfServiceBundle\Controller;
22
23
use Psr\Log\LoggerInterface;
24
use Surfnet\StepupBundle\Service\LoaResolutionService;
25
use Surfnet\StepupBundle\Value\PhoneNumber\InternationalPhoneNumber;
26
use Surfnet\StepupSelfService\SelfServiceBundle\Command\PromiseSafeStorePossessionCommand;
27
use Surfnet\StepupSelfService\SelfServiceBundle\Command\SafeStoreAuthenticationCommand;
28
use Surfnet\StepupSelfService\SelfServiceBundle\Command\SelfAssertedTokenRegistrationCommand;
29
use Surfnet\StepupSelfService\SelfServiceBundle\Command\SendRecoveryTokenSmsAuthenticationChallengeCommand;
30
use Surfnet\StepupSelfService\SelfServiceBundle\Command\VerifySmsRecoveryTokenChallengeCommand;
31
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\AuthenticateSafeStoreType;
32
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\PromiseSafeStorePossessionType;
33
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\VerifySmsChallengeType;
34
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SecondFactorService;
35
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SelfAssertedTokens\AuthenticationRequestFactory;
36
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SelfAssertedTokens\RecoveryTokenService;
37
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SelfAssertedTokens\SafeStoreService;
38
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SmsRecoveryTokenService;
39
use Symfony\Component\HttpFoundation\RedirectResponse;
40
use Symfony\Component\HttpFoundation\Request;
41
use Symfony\Component\HttpFoundation\Response;
42
use Symfony\Component\Routing\Attribute\Route;
43
44
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
45
 *
46
 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
47
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
48
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
49
class SelfAssertedTokensController extends Controller
50
{
51
    use RecoveryTokenControllerTrait;
0 ignored issues
show
Bug introduced by
The trait Surfnet\StepupSelfServic...eryTokenControllerTrait requires the property $id which is not provided by Surfnet\StepupSelfServic...ssertedTokensController.
Loading history...
52
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
53
     * @var RecoveryTokenService
54
     */
55
    private $recoveryTokenService;
0 ignored issues
show
Coding Style introduced by
Private member variable "recoveryTokenService" must be prefixed with an underscore
Loading history...
56
57
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
58
     * @var SecondFactorService
59
     */
60
    private $secondFactorService;
0 ignored issues
show
Coding Style introduced by
Private member variable "secondFactorService" must be prefixed with an underscore
Loading history...
61
62
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
63
     * @var SmsRecoveryTokenService
64
     */
65
    private $smsService;
0 ignored issues
show
Coding Style introduced by
Private member variable "smsService" must be prefixed with an underscore
Loading history...
66
67
    public function __construct(
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
68
        RecoveryTokenService $recoveryTokenService,
69
        private readonly SafeStoreService $safeStoreService,
70
        SecondFactorService $secondFactorService,
71
        SmsRecoveryTokenService $smsService,
72
        private readonly LoaResolutionService $loaResolutionService,
73
        private readonly AuthenticationRequestFactory $authnRequestFactory,
74
        private readonly LoggerInterface $logger
75
    ) {
76
        $this->recoveryTokenService = $recoveryTokenService;
77
        $this->secondFactorService = $secondFactorService;
78
        $this->smsService = $smsService;
79
    }
80
81
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
82
     * Self-asserted token registration: Registration entrypoint
83
     *
84
     * Select(s) the recovery token to perform the self-asserted second factor
85
     * token registration with.
86
     *
87
     * Possible outcomes:
88
     * 1. Shows a recovery token selection screen when more than one token are available
89
     * 2. Selects the one and only available recovery token and redirects to the recovery token authentication route
90
     * 3. Starts registration of a recovery token if non are in possession
91
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
92
    #[Route(
93
        path: '/second-factor/{secondFactorId}/self-asserted-token-registration',
94
        name: 'ss_second_factor_self_asserted_tokens',
95
        methods: ['GET'],
96
    )]
97
    public function selfAssertedTokenRegistration(string $secondFactorId): Response
98
    {
99
        $this->logger->info('Checking if Identity has a recovery token');
100
        $identity = $this->getIdentity();
101
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
102
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
103
        if ($this->recoveryTokenService->hasRecoveryToken($identity)) {
104
            $tokens = $this->recoveryTokenService->getAvailableTokens($identity, $secondFactor);
0 ignored issues
show
Bug introduced by
It seems like $secondFactor can also be of type null; however, parameter $secondFactor of Surfnet\StepupSelfServic...e::getAvailableTokens() does only seem to accept Surfnet\StepupMiddleware...to\VerifiedSecondFactor, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
            $tokens = $this->recoveryTokenService->getAvailableTokens($identity, /** @scrutinizer ignore-type */ $secondFactor);
Loading history...
105
            if ($tokens === []) {
106
                // User is in possession of a recovery token, but it is not safe to use here (for example sms recovery
107
                // token is not available while activating a SMS second factor)
108
                $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.no_available_recovery_token.alert.failed');
109
                return $this->redirectToRoute('ss_second_factor_list');
110
            }
111
            if (count($tokens) > 1) {
112
                $this->logger->info('Show recovery token selection screen');
113
                return $this->render(
114
                    'registration/self_asserted_tokens/select_available_recovery_token.html.twig',
115
                    [
116
                        'secondFactorId' => $secondFactorId,
117
                        'showAvailable' => true,
118
                        'availableRecoveryTokens' => $tokens,
119
                    ]
120
                );
121
            }
122
            $this->logger->info('Continue to recovery token authentication screen for the one available recovery token');
123
            $token = reset($tokens);
124
            return $this->redirect($this->generateUrl(
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
125
                'ss_second_factor_self_asserted_tokens_recovery_token',
126
                [
127
                    'secondFactorId' => $secondFactorId,
128
                    'recoveryTokenId' => $token->recoveryTokenId
129
                ]
130
            ));
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
131
        }
132
        $this->logger->info('Start registration of a recovery token (none are available yet)');
133
        return $this->redirect(
134
            $this->generateUrl('ss_second_factor_new_recovery_token', ['secondFactorId' => $secondFactorId])
135
        );
136
    }
137
138
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $request should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $recoveryTokenId should have a doc-comment as per coding-style.
Loading history...
139
     * Self-asserted token registration: Authenticate recovery token
140
     *
141
     * Identity must authenticate the recovery token in order to perform a
142
     * self-asserted token registration. But only when this action is
143
     * performed while recovering a Second Factor token. During initial
144
     * registration of a recovery token in the self-asserted token registration
145
     * flow, authentication is not required.
146
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
147
    #[Route(
148
        path: '/second-factor/{secondFactorId}/self-asserted-token-registration/{recoveryTokenId}',
149
        name: 'ss_second_factor_self_asserted_tokens_recovery_token',
150
        methods: ['GET','POST']
151
    )]
152
    public function selfAssertedTokenRegistrationRecoveryToken(
153
        Request $request,
154
        string $secondFactorId,
155
        string $recoveryTokenId
156
    ): Response {
157
        $this->logger->info('Start authentication of recovery token to perform self-asserted token registration');
158
        $identity = $this->getIdentity();
159
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
160
        $this->assertRecoveryTokenInPossession($recoveryTokenId, $identity);
161
        $token = $this->recoveryTokenService->getRecoveryToken($recoveryTokenId);
162
163
        switch ($token->type) {
164
            case "sms":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
165
                if ($this->smsService->wasTokenCreatedDuringSecondFactorRegistration()) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
166
                    // Forget we created the recovery token during token registration. Next time Identity
167
                    // must fill its password.
168
                    $this->smsService->forgetTokenCreatedDuringSecondFactorRegistration();
169
                    $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
170
171
                    $command = new SelfAssertedTokenRegistrationCommand();
172
                    $command->identity = $this->getIdentity();
173
                    $command->secondFactor = $secondFactor;
174
                    $command->recoveryTokenId = $recoveryTokenId;
175
176
                    if ($this->secondFactorService->registerSelfAssertedToken($command)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
177
                        $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.alert.successful');
178
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
179
                        $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.alert.failed');
180
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
181
                    return $this->redirectToRoute('ss_second_factor_list');
182
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
183
                $number = InternationalPhoneNumber::fromStringFormat($token->identifier);
184
                $command = new SendRecoveryTokenSmsAuthenticationChallengeCommand();
185
                $command->identifier = $number;
186
                $command->institution = $identity->institution;
187
                $command->recoveryTokenId = $recoveryTokenId;
188
                $command->identity = $identity->id;
189
                $this->smsService->authenticate($command);
190
                return $this->redirectToRoute(
191
                    'ss_second_factor_self_asserted_tokens_recovery_token_sms',
192
                    ['secondFactorId' => $secondFactorId, 'recoveryTokenId' => $recoveryTokenId]
193
                );
194
            case "safe-store":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
195
                // No authentication of the safe store token is required if created during SF token registration
196
                if ($this->safeStoreService->wasSafeStoreTokenCreatedDuringSecondFactorRegistration()) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
197
                    // Forget we created the safe-store recovery token during token registration. Next time Identity
198
                    // must fill its password.
199
                    $this->safeStoreService->forgetSafeStoreTokenCreatedDuringSecondFactorRegistration();
200
                    if ($this->invokeSelfAssertedTokenRegistrationCommand($secondFactorId, $recoveryTokenId)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
201
                        $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.vetting.alert.successful');
202
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
203
                        $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.vetting.alert.failed');
204
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
205
                    return $this->redirectToRoute('ss_second_factor_list');
206
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
207
                $command = new SafeStoreAuthenticationCommand();
208
                $command->recoveryToken = $token;
209
                $command->identity = $identity;
210
                $form = $this->createForm(AuthenticateSafeStoreType::class, $command)->handleRequest($request);
211
                if ($form->isSubmitted() && $form->isValid()) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
212
                    if ($this->recoveryTokenService->authenticateSafeStore($command)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
213
                        if ($this->invokeSelfAssertedTokenRegistrationCommand($secondFactorId, $recoveryTokenId)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
214
                            $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.vetting.alert.successful');
215
                            return $this->redirectToRoute('ss_second_factor_list');
216
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
217
                        $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.vetting.alert.failed');
218
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
219
                        $this->addFlash('error', 'ss.self_asserted_tokens.safe_store.authentication.alert.failed');
220
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
221
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
222
                return $this->render(
223
                    'registration/self_asserted_tokens/authenticate_safe_store.html.twig',
224
                    ['form' => $form->createView()]
225
                );
226
        }
227
    }
228
229
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
230
     * Self-asserted token registration: choose recovery token type
231
     *
232
     * The user can select which recovery token to add. Some limitations may
233
     * apply. For example, using a SMS Recovery Token for registration of an
234
     * SMS Second Factor is only allowed when different phone numbers are used.
235
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
236
    #[Route(
237
        path: '/second-factor/{secondFactorId}/new-recovery-token',
238
        name: 'ss_second_factor_new_recovery_token',
239
        methods: ['GET']
240
    )]
241
    public function newRecoveryToken(string $secondFactorId): Response
242
    {
243
        $this->logger->info('Determining which recovery token are available');
244
        $identity = $this->getIdentity();
245
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
246
        $this->assertNoRecoveryTokens($identity);
247
248
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
249
        $availableRecoveryTokens = $this->recoveryTokenService->getRemainingTokenTypes($identity);
250
        if ($secondFactor && $secondFactor->type === 'sms') {
251
            $this->logger->notice('SMS recovery token type is not allowed as we are vetting a SMS second factor');
252
            unset($availableRecoveryTokens['sms']);
253
        }
254
255
        return $this->render(
256
            'registration/self_asserted_tokens/new_recovery_token.html.twig',
257
            [
258
                'secondFactorId' => $secondFactorId,
259
                'availableRecoveryTokens' => $availableRecoveryTokens
260
            ]
261
        );
262
    }
263
264
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $request should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $recoveryTokenId should have a doc-comment as per coding-style.
Loading history...
265
     * Self-asserted token registration: Authenticate a SMS recovery token
266
     *
267
     * The previous action (selfAssertedTokenRegistrationRecoveryTokenAction)
268
     * sent the Identity a OTP via SMS. The Identity must reproduce that OTP
269
     * in this action. Proving possession of the recovery token.
270
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
271
    #[Route(
272
        path: '/second-factor/{secondFactorId}/self-asserted-token-registration/{recoveryTokenId}/authenticate',
273
        name: 'ss_second_factor_self_asserted_tokens_recovery_token_sms',
274
        methods: ['GET','POST']
275
    )]
276
    public function selfAssertedTokenRecoveryTokenSmsAuthentication(
277
        Request $request,
278
        string $secondFactorId,
279
        string $recoveryTokenId
280
    ): Response {
281
        $identity = $this->getIdentity();
282
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
283
        $this->assertRecoveryTokenInPossession($recoveryTokenId, $identity);
284
285
        // Then render the authentication (proof of possession screen
286
        if (!$this->smsService->hasSmsVerificationState($recoveryTokenId)) {
287
            $this->get('session')->getFlashBag()->add('notice', 'ss.registration.sms.alert.no_verification_state');
0 ignored issues
show
Bug introduced by
The method get() does not exist on Surfnet\StepupSelfServic...ssertedTokensController. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

287
            $this->/** @scrutinizer ignore-call */ 
288
                   get('session')->getFlashBag()->add('notice', 'ss.registration.sms.alert.no_verification_state');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
288
            return $this->redirectToRoute(
289
                'ss_second_factor_self_asserted_tokens',
290
                ['secondFactorId' => $secondFactorId]
291
            );
292
        }
293
294
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
295
296
        $command = new VerifySmsRecoveryTokenChallengeCommand();
297
        $command->identity = $identity->id;
298
        $command->resendRouteParameters = ['secondFactorId' => $secondFactorId, 'recoveryTokenId' => $recoveryTokenId];
299
300
        $form = $this->createForm(VerifySmsChallengeType::class, $command)->handleRequest($request);
301
302
        if ($form->isSubmitted() && $form->isValid()) {
303
            $command->recoveryTokenId = $recoveryTokenId;
304
            $result = $this->smsService->verifyAuthentication($command);
305
            if ($result->authenticated()) {
306
                $this->smsService->clearSmsVerificationState($recoveryTokenId);
307
308
                $command = new SelfAssertedTokenRegistrationCommand();
309
                $command->identity = $this->getIdentity();
310
                $command->secondFactor = $secondFactor;
311
                $command->recoveryTokenId = $recoveryTokenId;
312
313
                if ($this->secondFactorService->registerSelfAssertedToken($command)) {
314
                    $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.alert.successful');
315
                } else {
316
                    $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.alert.failed');
317
                }
318
319
                return $this->redirectToRoute('ss_second_factor_list');
320
            } elseif ($result->wasIncorrectChallengeResponseGiven()) {
321
                $this->addFlash('error', 'ss.prove_phone_possession.incorrect_challenge_response');
322
            } elseif ($result->hasChallengeExpired()) {
323
                $this->addFlash('error', 'ss.prove_phone_possession.challenge_expired');
324
            } elseif ($result->wereTooManyAttemptsMade()) {
325
                $this->addFlash('error', 'ss.prove_phone_possession.too_many_attempts');
326
            } else {
327
                $this->addFlash('error', 'ss.prove_phone_possession.proof_of_possession_failed');
328
            }
329
        }
330
        return $this->render(
331
            'registration/self_asserted_tokens/registration_sms_prove_possession.html.twig',
332
            [
333
                'form' => $form->createView(),
334
            ]
335
        );
336
    }
337
338
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $request should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
339
     * Self-asserted token registration: Create Recovery Token (safe-store)
340
     *
341
     * Shows the one-time secret and asks the Identity to store the
342
     * password in a safe location.
343
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
344
    #[Route(
345
        path: '/second-factor/{secondFactorId}/safe-store',
346
        name: 'ss_registration_recovery_token_safe_store',
347
        methods: ['GET','POST']
348
    )]
349
    public function registerCreateRecoveryTokenSafeStore(Request $request, string $secondFactorId): Response
350
    {
351
        $identity = $this->getIdentity();
352
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
353
        $this->assertNoRecoveryTokenOfType('safe-store', $identity);
354
355
        $secret = $this->safeStoreService->produceSecret();
356
        $command = new PromiseSafeStorePossessionCommand();
357
358
        $form = $this->createForm(PromiseSafeStorePossessionType::class, $command)->handleRequest($request);
359
360
        if ($form->isSubmitted() && $form->isValid()) {
361
            $command->secret = $secret;
362
            $command->identity = $this->getIdentity();
363
364
            $executionResult = $this->safeStoreService->promisePossession($command);
365
            if (!$executionResult->getErrors()) {
366
                return $this->redirect(
367
                    $this->generateUrl('ss_second_factor_self_asserted_tokens', ['secondFactorId' => $secondFactorId])
368
                );
369
            }
370
            $this->addFlash('error', 'ss.form.recovery_token.error.error_message');
371
        }
372
373
        return $this->render(
374
            'registration/self_asserted_tokens/recovery_token_safe_store.html.twig',
375
            [
376
                'form' => $form->createView(),
377
                'secondFactorId' => $secondFactorId,
378
                'secret' => $secret,
379
            ]
380
        );
381
    }
382
383
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $request should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
384
     * Self-asserted token registration: Create the SMS recovery token
385
     * Step 1: Send an OTP to phone of Identity
386
     *
387
     * Note: Shares logic with the recovery token SMS send challenge action
388
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
389
    #[Route(
390
        path: '/second-factor/{secondFactorId}/sms',
391
        name: 'ss_registration_recovery_token_sms',
392
        methods: ['GET','POST'],
393
    )]
394
    public function registerRecoveryTokenSms(Request $request, string $secondFactorId): Response
395
    {
396
        return $this->handleSmsChallenge(
397
            $request,
398
            'registration/self_asserted_tokens/recovery_token_sms.html.twig',
399
            'ss_registration_recovery_token_sms_proof_of_possession',
400
            $secondFactorId
401
        );
402
    }
403
404
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $request should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
405
     * Self-asserted token registration: Create the SMS recovery token
406
     * Step 2: Process proof of phone possession of Identity
407
     *
408
     * Note: Shares logic with the recovery token SMS send challenge action
409
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
410
    #[Route(
411
        path: '/recovery-token/{secondFactorId}/prove-sms-possession',
412
        name: 'ss_registration_recovery_token_sms_proof_of_possession',
413
        methods: ['GET', 'POST']
414
    )]
415
    public function registerRecoveryTokenSmsProofOfPossession(Request $request, string $secondFactorId): Response
416
    {
417
        return $this->handleSmsProofOfPossession(
418
            $request,
419
            'registration/self_asserted_tokens/registration_sms_prove_possession.html.twig',
420
            'ss_second_factor_self_asserted_tokens',
421
            $secondFactorId
422
        );
423
    }
424
425
    private function invokeSelfAssertedTokenRegistrationCommand(string $secondFactorId, string $recoveryTokenId): bool
0 ignored issues
show
Coding Style introduced by
Private method name "SelfAssertedTokensController::invokeSelfAssertedTokenRegistrationCommand" must be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing doc comment for function invokeSelfAssertedTokenRegistrationCommand()
Loading history...
426
    {
427
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
428
        $command = new SelfAssertedTokenRegistrationCommand();
429
        $command->identity = $this->getIdentity();
430
        $command->secondFactor = $secondFactor;
431
        $command->recoveryTokenId = $recoveryTokenId;
432
        return $this->secondFactorService->registerSelfAssertedToken($command);
433
    }
434
}
435