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

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

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