Passed
Pull Request — main (#308)
by Paul
14:53 queued 07:29
created

selfAssertedTokenRegistrationRecoveryToken()   C

Complexity

Conditions 11
Paths 10

Size

Total Lines 78
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 56
nc 10
nop 3
dl 0
loc 78
rs 6.8133
c 1
b 0
f 0

How to fix   Long Method    Complexity   

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\Bundle\FrameworkBundle\Controller\AbstractController;
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
 * TODO: Split up into smaller controllers
49
 */
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...
50
class SelfAssertedTokensController extends AbstractController
51
{
52
    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...
53
54
    public function __construct(
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
55
        private readonly RecoveryTokenService $recoveryTokenService,
56
        private readonly SafeStoreService $safeStoreService,
57
        private readonly SecondFactorService $secondFactorService,
58
        private readonly SmsRecoveryTokenService $smsService,
59
        private readonly LoaResolutionService $loaResolutionService,
60
        private readonly AuthenticationRequestFactory $authnRequestFactory,
61
        private readonly LoggerInterface $logger
62
    ) {
63
    }
64
65
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
66
     * Self-asserted token registration: Registration entrypoint
67
     *
68
     * Select(s) the recovery token to perform the self-asserted second factor
69
     * token registration with.
70
     *
71
     * Possible outcomes:
72
     * 1. Shows a recovery token selection screen when more than one token are available
73
     * 2. Selects the one and only available recovery token and redirects to the recovery token authentication route
74
     * 3. Starts registration of a recovery token if non are in possession
75
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
76
    #[Route(
77
        path: '/second-factor/{secondFactorId}/self-asserted-token-registration',
78
        name: 'ss_second_factor_self_asserted_tokens',
79
        methods: ['GET'],
80
    )]
81
    public function selfAssertedTokenRegistration(string $secondFactorId): Response
82
    {
83
        $this->logger->info('Checking if Identity has a recovery token');
84
        $identity = $this->getUser()->getIdentity();
0 ignored issues
show
Bug introduced by
The method getIdentity() does not exist on Symfony\Component\Security\Core\User\UserInterface. It seems like you code against a sub-type of Symfony\Component\Security\Core\User\UserInterface such as Surfnet\StepupSelfServic...n\AuthenticatedIdentity. ( Ignorable by Annotation )

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

84
        $identity = $this->getUser()->/** @scrutinizer ignore-call */ getIdentity();
Loading history...
85
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
86
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
87
        if ($this->recoveryTokenService->hasRecoveryToken($identity)) {
88
            $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

88
            $tokens = $this->recoveryTokenService->getAvailableTokens($identity, /** @scrutinizer ignore-type */ $secondFactor);
Loading history...
89
            if ($tokens === []) {
90
                // User is in possession of a recovery token, but it is not safe to use here (for example sms recovery
91
                // token is not available while activating a SMS second factor)
92
                $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.no_available_recovery_token.alert.failed');
93
                return $this->redirectToRoute('ss_second_factor_list');
94
            }
95
            if (count($tokens) > 1) {
96
                $this->logger->info('Show recovery token selection screen');
97
                return $this->render(
98
                    'registration/self_asserted_tokens/select_available_recovery_token.html.twig',
99
                    [
100
                        'secondFactorId' => $secondFactorId,
101
                        'showAvailable' => true,
102
                        'availableRecoveryTokens' => $tokens,
103
                    ]
104
                );
105
            }
106
            $this->logger->info('Continue to recovery token authentication screen for the one available recovery token');
107
            $token = reset($tokens);
108
            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...
109
                'ss_second_factor_self_asserted_tokens_recovery_token',
110
                [
111
                    'secondFactorId' => $secondFactorId,
112
                    'recoveryTokenId' => $token->recoveryTokenId
113
                ]
114
            ));
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...
115
        }
116
        $this->logger->info('Start registration of a recovery token (none are available yet)');
117
        return $this->redirect(
118
            $this->generateUrl('ss_second_factor_new_recovery_token', ['secondFactorId' => $secondFactorId])
119
        );
120
    }
121
122
    /**
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...
123
     * Self-asserted token registration: Authenticate recovery token
124
     *
125
     * Identity must authenticate the recovery token in order to perform a
126
     * self-asserted token registration. But only when this action is
127
     * performed while recovering a Second Factor token. During initial
128
     * registration of a recovery token in the self-asserted token registration
129
     * flow, authentication is not required.
130
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
131
    #[Route(
132
        path: '/second-factor/{secondFactorId}/self-asserted-token-registration/{recoveryTokenId}',
133
        name: 'ss_second_factor_self_asserted_tokens_recovery_token',
134
        methods: ['GET','POST']
135
    )]
136
    public function selfAssertedTokenRegistrationRecoveryToken(
137
        Request $request,
138
        string $secondFactorId,
139
        string $recoveryTokenId
140
    ): Response {
141
        $this->logger->info('Start authentication of recovery token to perform self-asserted token registration');
142
        $identity = $this->getUser()->getIdentity();
143
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
144
        $this->assertRecoveryTokenInPossession($recoveryTokenId, $identity);
145
        $token = $this->recoveryTokenService->getRecoveryToken($recoveryTokenId);
146
147
        switch ($token->type) {
148
            case "sms":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
149
                if ($this->smsService->wasTokenCreatedDuringSecondFactorRegistration()) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
150
                    // Forget we created the recovery token during token registration. Next time Identity
151
                    // must fill its password.
152
                    $this->smsService->forgetTokenCreatedDuringSecondFactorRegistration();
153
                    $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
154
155
                    $command = new SelfAssertedTokenRegistrationCommand();
156
                    $command->identity = $this->getUser()->getIdentity();
157
                    $command->secondFactor = $secondFactor;
158
                    $command->recoveryTokenId = $recoveryTokenId;
159
160
                    if ($this->secondFactorService->registerSelfAssertedToken($command)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
161
                        $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.alert.successful');
162
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
163
                        $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.alert.failed');
164
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
165
                    return $this->redirectToRoute('ss_second_factor_list');
166
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
167
                $number = InternationalPhoneNumber::fromStringFormat($token->identifier);
168
                $command = new SendRecoveryTokenSmsAuthenticationChallengeCommand();
169
                $command->identifier = $number;
170
                $command->institution = $identity->institution;
171
                $command->recoveryTokenId = $recoveryTokenId;
172
                $command->identity = $identity->id;
173
                $this->smsService->authenticate($command);
174
                return $this->redirectToRoute(
175
                    'ss_second_factor_self_asserted_tokens_recovery_token_sms',
176
                    ['secondFactorId' => $secondFactorId, 'recoveryTokenId' => $recoveryTokenId]
177
                );
178
            case "safe-store":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
179
                // No authentication of the safe store token is required if created during SF token registration
180
                if ($this->safeStoreService->wasSafeStoreTokenCreatedDuringSecondFactorRegistration()) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
181
                    // Forget we created the safe-store recovery token during token registration. Next time Identity
182
                    // must fill its password.
183
                    $this->safeStoreService->forgetSafeStoreTokenCreatedDuringSecondFactorRegistration();
184
                    if ($this->invokeSelfAssertedTokenRegistrationCommand($secondFactorId, $recoveryTokenId)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
185
                        $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.vetting.alert.successful');
186
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
187
                        $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.vetting.alert.failed');
188
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
189
                    return $this->redirectToRoute('ss_second_factor_list');
190
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
191
                $command = new SafeStoreAuthenticationCommand();
192
                $command->recoveryToken = $token;
193
                $command->identity = $identity->id;
194
                $form = $this->createForm(AuthenticateSafeStoreType::class, $command)->handleRequest($request);
195
                if ($form->isSubmitted() && $form->isValid()) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
196
                    if ($this->recoveryTokenService->authenticateSafeStore($command)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
197
                        if ($this->invokeSelfAssertedTokenRegistrationCommand($secondFactorId, $recoveryTokenId)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
198
                            $this->addFlash('success', 'ss.self_asserted_tokens.second_factor.vetting.alert.successful');
199
                            return $this->redirectToRoute('ss_second_factor_list');
200
                        }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 20 spaces, found 24
Loading history...
201
                        $this->addFlash('error', 'ss.self_asserted_tokens.second_factor.vetting.alert.failed');
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.safe_store.authentication.alert.failed');
204
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
205
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
206
                return $this->render(
207
                    'registration/self_asserted_tokens/authenticate_safe_store.html.twig',
208
                    ['form' => $form->createView()]
209
                );
210
        }
211
    }
212
213
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $secondFactorId should have a doc-comment as per coding-style.
Loading history...
214
     * Self-asserted token registration: choose recovery token type
215
     *
216
     * The user can select which recovery token to add. Some limitations may
217
     * apply. For example, using a SMS Recovery Token for registration of an
218
     * SMS Second Factor is only allowed when different phone numbers are used.
219
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
220
    #[Route(
221
        path: '/second-factor/{secondFactorId}/new-recovery-token',
222
        name: 'ss_second_factor_new_recovery_token',
223
        methods: ['GET']
224
    )]
225
    public function newRecoveryToken(string $secondFactorId): Response
226
    {
227
        $this->logger->info('Determining which recovery token are available');
228
        $identity = $this->getUser()->getIdentity();
229
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
230
        $this->assertNoRecoveryTokens($identity);
231
232
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
233
        $availableRecoveryTokens = $this->recoveryTokenService->getRemainingTokenTypes($identity);
234
        if ($secondFactor && $secondFactor->type === 'sms') {
235
            $this->logger->notice('SMS recovery token type is not allowed as we are vetting a SMS second factor');
236
            unset($availableRecoveryTokens['sms']);
237
        }
238
239
        return $this->render(
240
            'registration/self_asserted_tokens/new_recovery_token.html.twig',
241
            [
242
                'secondFactorId' => $secondFactorId,
243
                'availableRecoveryTokens' => $availableRecoveryTokens
244
            ]
245
        );
246
    }
247
248
    /**
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...
249
     * Self-asserted token registration: Authenticate a SMS recovery token
250
     *
251
     * The previous action (selfAssertedTokenRegistrationRecoveryTokenAction)
252
     * sent the Identity a OTP via SMS. The Identity must reproduce that OTP
253
     * in this action. Proving possession of the recovery token.
254
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
255
    #[Route(
256
        path: '/second-factor/{secondFactorId}/self-asserted-token-registration/{recoveryTokenId}/authenticate',
257
        name: 'ss_second_factor_self_asserted_tokens_recovery_token_sms',
258
        methods: ['GET','POST']
259
    )]
260
    public function selfAssertedTokenRecoveryTokenSmsAuthentication(
261
        Request $request,
262
        string $secondFactorId,
263
        string $recoveryTokenId
264
    ): Response {
265
        $identity = $this->getUser()->getIdentity();
266
        $this->assertSecondFactorInPossession($secondFactorId, $identity);
267
        $this->assertRecoveryTokenInPossession($recoveryTokenId, $identity);
268
269
        // Then render the authentication (proof of possession screen
270
        if (!$this->smsService->hasSmsVerificationState($recoveryTokenId)) {
271
            $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

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