Passed
Pull Request — develop (#302)
by Michiel
10:08 queued 05:22
created

selectSecondFactorForVerificationSfoAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Copyright 2014 SURFnet bv
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\StepupGateway\GatewayBundle\Controller;
20
21
use Psr\Log\LoggerInterface;
22
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
23
use Surfnet\StepupBundle\Command\VerifyPossessionOfPhoneCommand;
24
use Surfnet\StepupBundle\Value\PhoneNumber\InternationalPhoneNumber;
25
use Surfnet\StepupBundle\Value\SecondFactorType;
26
use Surfnet\StepupGateway\GatewayBundle\Command\ChooseSecondFactorCommand;
27
use Surfnet\StepupGateway\GatewayBundle\Command\SendSmsChallengeCommand;
28
use Surfnet\StepupGateway\GatewayBundle\Command\VerifyYubikeyOtpCommand;
29
use Surfnet\StepupGateway\GatewayBundle\Entity\SecondFactor;
30
use Surfnet\StepupGateway\GatewayBundle\Exception\InvalidArgumentException;
31
use Surfnet\StepupGateway\GatewayBundle\Exception\LoaCannotBeGivenException;
32
use Surfnet\StepupGateway\GatewayBundle\Exception\RuntimeException;
33
use Surfnet\StepupGateway\GatewayBundle\Form\Type\CancelAuthenticationType;
34
use Surfnet\StepupGateway\GatewayBundle\Form\Type\ChooseSecondFactorType;
35
use Surfnet\StepupGateway\GatewayBundle\Form\Type\SendSmsChallengeType;
36
use Surfnet\StepupGateway\GatewayBundle\Form\Type\VerifySmsChallengeType;
37
use Surfnet\StepupGateway\GatewayBundle\Form\Type\VerifyYubikeyOtpType;
38
use Surfnet\StepupGateway\GatewayBundle\Saml\ResponseContext;
39
use Surfnet\StepupGateway\GatewayBundle\Service\SecondFactorService;
40
use Surfnet\StepupGateway\GatewayBundle\Sso2fa\CookieService;
41
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
42
use Symfony\Component\Form\FormError;
43
use Symfony\Component\Form\FormInterface;
44
use Symfony\Component\HttpFoundation\RedirectResponse;
45
use Symfony\Component\HttpFoundation\Request;
46
use Symfony\Component\HttpFoundation\Response;
47
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
48
49
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
50
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
51
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
52
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
53
 */
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...
54
class SecondFactorController extends Controller
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Bundle\Framework...e\Controller\Controller has been deprecated: since Symfony 4.2, use "Symfony\Bundle\FrameworkBundle\Controller\AbstractController" instead. ( Ignorable by Annotation )

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

54
class SecondFactorController extends /** @scrutinizer ignore-deprecated */ Controller
Loading history...
55
{
56
    const MODE_SFO = 'sfo';
57
    const MODE_SSO = 'sso';
58
59
    public function selectSecondFactorForVerificationSsoAction(Request $request)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function selectSecondFactorForVerificationSsoAction()
Loading history...
60
    {
61
        return $this->selectSecondFactorForVerificationAction(self::MODE_SSO, $request);
62
    }
63
64
    public function selectSecondFactorForVerificationSfoAction(Request $request)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function selectSecondFactorForVerificationSfoAction()
Loading history...
65
    {
66
        return $this->selectSecondFactorForVerificationAction(self::MODE_SFO, $request);
67
    }
68
69
    public function selectSecondFactorForVerificationAction($authenticationMode, Request $request)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function selectSecondFactorForVerificationAction()
Loading history...
70
    {
71
        $this->supportsAuthenticationMode($authenticationMode);
72
        $context = $this->getResponseContext($authenticationMode);
73
        $originalRequestId = $context->getInResponseTo();
74
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
75
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
76
        $logger->notice('Determining which second factor to use...');
77
        try {
78
            // Retrieve all requirements to determine the required LoA
79
            $requestedLoa = $context->getRequiredLoa();
80
            $spConfiguredLoas = $context->getServiceProvider()->get('configuredLoas');
81
            $identityNameId = $context->getIdentityNameId();
82
            $normalizedIdpSho = $context->getNormalizedSchacHomeOrganization();
83
            $normalizedUserSho = $this->getStepupService()->getNormalizedUserShoByIdentityNameId($identityNameId);
84
            $requiredLoa = $this
85
                ->getStepupService()
86
                ->resolveHighestRequiredLoa(
87
                    $requestedLoa,
88
                    $spConfiguredLoas,
0 ignored issues
show
Bug introduced by
It seems like $spConfiguredLoas can also be of type null; however, parameter $spConfiguredLoas of Surfnet\StepupGateway\Ga...lveHighestRequiredLoa() does only seem to accept array, 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
                    /** @scrutinizer ignore-type */ $spConfiguredLoas,
Loading history...
89
                    $normalizedIdpSho,
90
                    $normalizedUserSho
91
                );
92
        } catch (LoaCannotBeGivenException $e) {
93
            // Log the message of the domain exception, this contains a meaningful message.
94
            $logger->notice($e->getMessage());
95
            return $this->forward(
96
                'SurfnetStepupGatewayGatewayBundle:Gateway:sendLoaCannotBeGiven',
97
                ['authenticationMode' => $authenticationMode]
98
            );
99
        }
100
101
        $logger->notice(sprintf('Determined that the required Loa is "%s"', $requiredLoa));
102
        if ($this->getStepupService()->isIntrinsicLoa($requiredLoa)) {
103
            $this->get('gateway.authentication_logger')->logIntrinsicLoaAuthentication($originalRequestId);
104
            return $this->forward($context->getResponseAction());
0 ignored issues
show
Bug introduced by
It seems like $context->getResponseAction() can also be of type null; however, parameter $controller of Symfony\Bundle\Framework...r\Controller::forward() does only seem to accept string, 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
            return $this->forward(/** @scrutinizer ignore-type */ $context->getResponseAction());
Loading history...
105
        }
106
107
        // The preconditions must be met in order to give SSO on 2FA
108
        // 1: AuthNRequest is not force authn. 2: The SP allows SSO on 2FA.
109
        if ($this->getCookieService()->preconditionsAreMet($context)) {
110
            // Now read the SSO cookie
111
            $ssoCookie = $this->getCookieService()->read($request);
112
            // Test if the SSO cookie can satisfy the second factor authentication requirements
113
            if ($this->getCookieService()->maySkipAuthentication($requiredLoa->getLevel(), $identityNameId, $ssoCookie)) {
114
                $logger->notice(
115
                    'Skipping second factor authentication. Required LoA was met by the LoA recorded in the cookie',
116
                    [
117
                        'required-loa' => $requiredLoa->getLevel(),
118
                        'cookie-loa' => $ssoCookie->getLoa()
119
                    ]
120
                );
121
                // We use the SF from the cookie as the SF that was used for authenticating the second factor authentication
122
                $secondFactor = $this->getSecondFactorService()->findByUuid($ssoCookie->secondFactorId());
123
                $this->getResponseContext($authenticationMode)->saveSelectedSecondFactor($secondFactor);
0 ignored issues
show
Bug introduced by
It seems like $secondFactor can also be of type null; however, parameter $secondFactor of Surfnet\StepupGateway\Ga...eSelectedSecondFactor() does only seem to accept Surfnet\StepupGateway\Ga...dle\Entity\SecondFactor, 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

123
                $this->getResponseContext($authenticationMode)->saveSelectedSecondFactor(/** @scrutinizer ignore-type */ $secondFactor);
Loading history...
124
                $this->getResponseContext($authenticationMode)->markSecondFactorVerified();
125
                $this->getResponseContext($authenticationMode)->markVerifiedBySsoOn2faCookie(
126
                    $this->getCookieService()->getCookieFingerprint($request)
127
                );
128
                $this->getAuthenticationLogger()->logSecondFactorAuthentication($originalRequestId, $authenticationMode);
0 ignored issues
show
Bug introduced by
It seems like $originalRequestId can also be of type null; however, parameter $requestId of Surfnet\StepupGateway\Ga...dFactorAuthentication() does only seem to accept string, 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

128
                $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
129
                return $this->forward($context->getResponseAction());
130
            }
131
        }
132
133
        $secondFactorCollection = $this
134
            ->getStepupService()
135
            ->determineViableSecondFactors(
136
                $context->getIdentityNameId(),
137
                $requiredLoa,
138
                $this->get('gateway.service.whitelist')
139
            );
140
        switch (count($secondFactorCollection)) {
141
            case 0:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
142
                $logger->notice('No second factors can give the determined Loa');
143
                return $this->forward(
144
                    'SurfnetStepupGatewayGatewayBundle:Gateway:sendLoaCannotBeGiven',
145
                    ['authenticationMode' => $authenticationMode]
146
                );
147
            case 1:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
148
                $secondFactor = $secondFactorCollection->first();
149
                $logger->notice(sprintf(
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...
150
                    'Found "%d" second factors, using second factor of type "%s"',
151
                    count($secondFactorCollection),
152
                    $secondFactor->secondFactorType
153
                ));
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...
154
                return $this->selectAndRedirectTo($secondFactor, $context, $authenticationMode);
155
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
156
                return $this->forward(
157
                    'SurfnetStepupGatewayGatewayBundle:SecondFactor:chooseSecondFactor',
158
                    ['authenticationMode' => $authenticationMode, 'secondFactors' => $secondFactorCollection]
159
                );
160
        }
161
    }
162
163
    /**
164
     * The main WAYG screen
165
     * - Shows the token selection screen if you own > 1 token
166
     * - Directly goes to SF auth when identity owns 1 token
167
     *
168
     * @Template
0 ignored issues
show
Coding Style introduced by
Tag @Template cannot be grouped with parameter tags in a doc comment
Loading history...
169
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 41 spaces but found 1
Loading history...
170
     * @param string $authenticationMode
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 41 spaces but found 1
Loading history...
171
     * @return array|RedirectResponse|Response
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 40 spaces but found 1
Loading history...
172
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
0 ignored issues
show
Coding Style introduced by
Tag @SuppressWarnings(PHPMD.ExcessiveMethodLength) cannot be grouped with parameter tags in a doc comment
Loading history...
173
     */
174
    public function chooseSecondFactorAction(Request $request, $authenticationMode)
175
    {
176
        $this->supportsAuthenticationMode($authenticationMode);
177
        $context = $this->getResponseContext($authenticationMode);
178
        $originalRequestId = $context->getInResponseTo();
179
180
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
181
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
182
        $logger->notice('Ask the user which one of his suitable second factor tokens to use...');
183
184
        try {
185
            // Retrieve all requirements to determine the required LoA
186
            $requestedLoa = $context->getRequiredLoa();
187
            $spConfiguredLoas = $context->getServiceProvider()->get('configuredLoas');
188
189
            $normalizedIdpSho = $context->getNormalizedSchacHomeOrganization();
190
            $normalizedUserSho = $this->getStepupService()->getNormalizedUserShoByIdentityNameId($context->getIdentityNameId());
191
192
            $requiredLoa = $this
193
                ->getStepupService()
194
                ->resolveHighestRequiredLoa(
195
                    $requestedLoa,
196
                    $spConfiguredLoas,
0 ignored issues
show
Bug introduced by
It seems like $spConfiguredLoas can also be of type null; however, parameter $spConfiguredLoas of Surfnet\StepupGateway\Ga...lveHighestRequiredLoa() does only seem to accept array, 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

196
                    /** @scrutinizer ignore-type */ $spConfiguredLoas,
Loading history...
197
                    $normalizedIdpSho,
198
                    $normalizedUserSho
199
                );
200
        } catch (LoaCannotBeGivenException $e) {
201
            // Log the message of the domain exception, this contains a meaningful message.
202
            $logger->notice($e->getMessage());
203
            return $this->forward('SurfnetStepupGatewayGatewayBundle:Gateway:sendLoaCannotBeGiven');
204
        }
205
206
        $logger->notice(sprintf('Determined that the required Loa is "%s"', $requiredLoa));
207
208
        $secondFactors = $this
209
            ->getStepupService()
210
            ->determineViableSecondFactors(
211
                $context->getIdentityNameId(),
212
                $requiredLoa,
213
                $this->get('gateway.service.whitelist')
214
            );
215
216
        $command = new ChooseSecondFactorCommand();
217
        $command->secondFactors = $secondFactors;
0 ignored issues
show
Documentation Bug introduced by
It seems like $secondFactors of type Doctrine\Common\Collections\Collection is incompatible with the declared type Surfnet\StepupGateway\Ga...e\Entity\SecondFactor[] of property $secondFactors.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
218
219
        $form = $this
220
            ->createForm(
221
                ChooseSecondFactorType::class,
222
                $command,
223
                ['action' => $this->generateUrl('gateway_verify_second_factor_choose_second_factor', ['authenticationMode' => $authenticationMode])]
224
            )
225
            ->handleRequest($request);
226
        $cancelForm = $this->buildCancelAuthenticationForm($authenticationMode)->handleRequest($request);
227
228
        if ($form->isSubmitted() && $form->isValid()) {
229
            $buttonName = $form->getClickedButton()->getName();
0 ignored issues
show
Bug introduced by
The method getClickedButton() does not exist on Symfony\Component\Form\FormInterface. It seems like you code against a sub-type of Symfony\Component\Form\FormInterface such as Symfony\Component\Form\Form. ( Ignorable by Annotation )

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

229
            $buttonName = $form->/** @scrutinizer ignore-call */ getClickedButton()->getName();
Loading history...
230
            $formResults = $request->request->get('gateway_choose_second_factor', false);
231
232
            if (!isset($formResults[$buttonName])) {
233
                throw new InvalidArgumentException(
234
                    sprintf(
235
                        'Second factor type "%s" could not be found in the posted form results.',
236
                        $buttonName
237
                    )
238
                );
239
            }
240
241
            $secondFactorType = $formResults[$buttonName];
242
243
            // Filter the selected second factor from the array collection
244
            $secondFactorFiltered = $secondFactors->filter(
245
                function ($secondFactor) use ($secondFactorType) {
246
                    return $secondFactorType === $secondFactor->secondFactorType;
247
                }
248
            );
249
250
            if ($secondFactorFiltered->isEmpty()) {
251
                throw new InvalidArgumentException(
252
                    sprintf(
253
                        'Second factor type "%s" could not be found in the collection of available second factors.',
254
                        $secondFactorType
255
                    )
256
                );
257
            }
258
259
            $secondFactor = $secondFactorFiltered->first();
260
261
            $logger->notice(sprintf('User chose "%s" to use as second factor', $secondFactorType));
262
263
            // Forward to action to verify possession of second factor
264
            return $this->selectAndRedirectTo($secondFactor, $context, $authenticationMode);
265
        } else if ($form->isSubmitted() && !$form->isValid()) {
266
            $form->addError(
267
                new FormError(
268
                    $this->get('translator')
269
                      ->trans('gateway.form.gateway_choose_second_factor.unknown_second_factor_type')
0 ignored issues
show
Coding Style introduced by
Object operator not indented correctly; expected 24 spaces but found 22
Loading history...
270
                )
271
            );
272
        }
273
274
        return [
275
            'form' => $form->createView(),
276
            'cancelForm' => $cancelForm->createView(),
277
            'secondFactors' => $secondFactors,
278
        ];
279
    }
280
281
    public function verifyGssfAction(Request $request)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function verifyGssfAction()
Loading history...
282
    {
283
        if (!$request->get('authenticationMode', false)) {
284
            throw new RuntimeException('Unable to determine the authentication mode in the GSSP verification action');
285
        }
286
        $authenticationMode = $request->get('authenticationMode');
287
        $this->supportsAuthenticationMode($authenticationMode);
288
        $context = $this->getResponseContext($authenticationMode);
289
290
        $originalRequestId = $context->getInResponseTo();
291
292
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
293
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
294
        $logger->info('Received request to verify GSSF');
295
296
        $selectedSecondFactor = $this->getSelectedSecondFactor($context, $logger);
297
298
        $logger->info(sprintf(
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...
299
            'Selected GSSF "%s" for verfication, forwarding to Saml handling',
300
            $selectedSecondFactor
301
        ));
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...
302
303
        /** @var \Surfnet\StepupGateway\GatewayBundle\Service\SecondFactorService $secondFactorService */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
304
        $secondFactorService = $this->get('gateway.service.second_factor_service');
305
        /** @var \Surfnet\StepupGateway\GatewayBundle\Entity\SecondFactor $secondFactor */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
306
        $secondFactor = $secondFactorService->findByUuid($selectedSecondFactor);
307
        if (!$secondFactor) {
0 ignored issues
show
introduced by
$secondFactor is of type Surfnet\StepupGateway\Ga...dle\Entity\SecondFactor, thus it always evaluated to true.
Loading history...
308
            throw new RuntimeException(sprintf(
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...
309
                'Requested verification of GSSF "%s", however that Second Factor no longer exists',
310
                $selectedSecondFactor
311
            ));
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...
312
        }
313
314
        // Also send the response context service id, as later we need to know if this is regular SSO or SFO authn.
315
        $responseContextServiceId = $context->getResponseContextServiceId();
316
317
        return $this->forward(
318
            'SurfnetStepupGatewaySamlStepupProviderBundle:SamlProxy:sendSecondFactorVerificationAuthnRequest',
319
            [
320
                'provider' => $secondFactor->secondFactorType,
321
                'subjectNameId' => $secondFactor->secondFactorIdentifier,
322
                'responseContextServiceId' => $responseContextServiceId,
323
            ]
324
        );
325
    }
326
327
    public function gssfVerifiedAction(Request $request)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function gssfVerifiedAction()
Loading history...
328
    {
329
        $authenticationMode = $request->get('authenticationMode');
330
        $this->supportsAuthenticationMode($authenticationMode);
331
        $context = $this->getResponseContext($authenticationMode);
332
333
        $originalRequestId = $context->getInResponseTo();
334
335
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
336
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
337
        $logger->info('Attempting to mark GSSF as verified');
338
339
        $selectedSecondFactor = $this->getSelectedSecondFactor($context, $logger);
340
341
        /** @var \Surfnet\StepupGateway\GatewayBundle\Entity\SecondFactor $secondFactor */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
342
        $secondFactor = $this->get('gateway.service.second_factor_service')->findByUuid($selectedSecondFactor);
343
        if (!$secondFactor) {
0 ignored issues
show
introduced by
$secondFactor is of type Surfnet\StepupGateway\Ga...dle\Entity\SecondFactor, thus it always evaluated to true.
Loading history...
344
            throw new RuntimeException(
345
                sprintf(
346
                    'Verification of GSSF "%s" succeeded, however that Second Factor no longer exists',
347
                    $selectedSecondFactor
348
                )
349
            );
350
        }
351
352
        $this->getAuthenticationLogger()->logSecondFactorAuthentication($originalRequestId, $authenticationMode);
0 ignored issues
show
Bug introduced by
It seems like $originalRequestId can also be of type null; however, parameter $requestId of Surfnet\StepupGateway\Ga...dFactorAuthentication() does only seem to accept string, 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

352
        $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
353
        $context->markSecondFactorVerified();
354
355
        $logger->info(sprintf(
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...
356
            'Marked GSSF "%s" as verified, forwarding to Gateway controller to respond',
357
            $selectedSecondFactor
358
        ));
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...
359
        return $this->forward($context->getResponseAction());
0 ignored issues
show
Bug introduced by
It seems like $context->getResponseAction() can also be of type null; however, parameter $controller of Symfony\Bundle\Framework...r\Controller::forward() does only seem to accept string, 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

359
        return $this->forward(/** @scrutinizer ignore-type */ $context->getResponseAction());
Loading history...
360
    }
361
362
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
363
     * @Template
0 ignored issues
show
Coding Style introduced by
Tag @Template cannot be grouped with parameter tags in a doc comment
Loading history...
364
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 4 spaces but found 1
Loading history...
365
     * @return array|Response
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 3 spaces but found 1
Loading history...
366
     */
367
    public function verifyYubiKeySecondFactorAction(Request $request)
368
    {
369
        if (!$request->get('authenticationMode', false)) {
370
            throw new RuntimeException('Unable to determine the authentication mode in Yubikey verification action');
371
        }
372
        $authenticationMode = $request->get('authenticationMode');
373
        $this->supportsAuthenticationMode($authenticationMode);
374
        $context = $this->getResponseContext($authenticationMode);
375
        $originalRequestId = $context->getInResponseTo();
376
377
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
378
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
379
380
        $selectedSecondFactor = $this->getSelectedSecondFactor($context, $logger);
381
382
        $logger->notice('Verifying possession of Yubikey second factor');
383
384
        $command = new VerifyYubikeyOtpCommand();
385
        $command->secondFactorId = $selectedSecondFactor;
386
387
        $form = $this->createForm(VerifyYubikeyOtpType::class, $command)->handleRequest($request);
388
        $cancelForm = $this->buildCancelAuthenticationForm($authenticationMode)->handleRequest($request);
389
390
        if ($form->isSubmitted()  && $form->isValid()) {
391
            $result = $this->getStepupService()->verifyYubikeyOtp($command);
392
            if ($result->didOtpVerificationFail()) {
393
                $form->addError(
394
                    new FormError($this->get('translator')->trans('gateway.form.verify_yubikey.otp_verification_failed'))
395
                );
396
397
                // OTP field is rendered empty in the template.
398
                return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
399
            } elseif (!$result->didPublicIdMatch()) {
400
                $form->addError(
401
                    new FormError($this->get('translator')->trans('gateway.form.verify_yubikey.public_id_mismatch'))
402
                );
403
404
                // OTP field is rendered empty in the template.
405
                return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
406
            }
407
408
            $this->getResponseContext($authenticationMode)->markSecondFactorVerified();
409
            $this->getAuthenticationLogger()->logSecondFactorAuthentication($originalRequestId, $authenticationMode);
0 ignored issues
show
Bug introduced by
It seems like $originalRequestId can also be of type null; however, parameter $requestId of Surfnet\StepupGateway\Ga...dFactorAuthentication() does only seem to accept string, 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

409
            $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
410
411
            $logger->info(
412
                sprintf(
413
                    'Marked Yubikey Second Factor "%s" as verified, forwarding to Saml Proxy to respond',
414
                    $selectedSecondFactor
415
                )
416
            );
417
            return $this->forward($context->getResponseAction());
0 ignored issues
show
Bug introduced by
It seems like $context->getResponseAction() can also be of type null; however, parameter $controller of Symfony\Bundle\Framework...r\Controller::forward() does only seem to accept string, 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

417
            return $this->forward(/** @scrutinizer ignore-type */ $context->getResponseAction());
Loading history...
418
        }
419
420
        // OTP field is rendered empty in the template.
421
        return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
422
    }
423
424
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
425
     * @Template
0 ignored issues
show
Coding Style introduced by
Tag @Template cannot be grouped with parameter tags in a doc comment
Loading history...
426
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 4 spaces but found 1
Loading history...
427
     * @param string $authenticationMode
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Superfluous parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 4 spaces but found 1
Loading history...
428
     * @return array|Response
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 3 spaces but found 1
Loading history...
429
     */
430
    public function verifySmsSecondFactorAction(Request $request)
431
    {
432
        if (!$request->get('authenticationMode', false)) {
433
            throw new RuntimeException('Unable to determine the authentication mode in the SMS verification action');
434
        }
435
        $authenticationMode = $request->get('authenticationMode');
436
        $this->supportsAuthenticationMode($authenticationMode);
437
        $context = $this->getResponseContext($authenticationMode);
438
        $originalRequestId = $context->getInResponseTo();
439
440
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
441
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
442
443
        $selectedSecondFactor = $this->getSelectedSecondFactor($context, $logger);
444
445
        $logger->notice('Verifying possession of SMS second factor, preparing to send');
446
447
        $command = new SendSmsChallengeCommand();
448
        $command->secondFactorId = $selectedSecondFactor;
449
450
        $form = $this->createForm(SendSmsChallengeType::class, $command)->handleRequest($request);
451
        $cancelForm = $this->buildCancelAuthenticationForm($authenticationMode)->handleRequest($request);
452
453
        $stepupService = $this->getStepupService();
454
        $phoneNumber = InternationalPhoneNumber::fromStringFormat(
455
            $stepupService->getSecondFactorIdentifier($selectedSecondFactor)
456
        );
457
458
        $otpRequestsRemaining = $stepupService->getSmsOtpRequestsRemainingCount($selectedSecondFactor);
459
        $maximumOtpRequests = $stepupService->getSmsMaximumOtpRequestsCount();
460
        $viewVariables = ['otpRequestsRemaining' => $otpRequestsRemaining, 'maximumOtpRequests' => $maximumOtpRequests];
461
462
        if ($form->isSubmitted() && !$form->isValid()) {
463
            return array_merge(
464
                $viewVariables,
465
                [
466
                    'phoneNumber' => $phoneNumber,
467
                    'form' => $form->createView(),
468
                    'cancelForm' => $cancelForm->createView()
469
                ]
470
            );
471
        }
472
473
        $logger->notice('Verifying possession of SMS second factor, sending challenge per SMS');
474
475
        if (!$stepupService->sendSmsChallenge($command)) {
476
            $form->addError(
477
                new FormError($this->get('translator')->trans('gateway.form.send_sms_challenge.sms_sending_failed'))
478
            );
479
480
            return array_merge(
481
                $viewVariables,
482
                [
483
                    'phoneNumber' => $phoneNumber,
484
                    'form' => $form->createView(),
485
                    'cancelForm' => $cancelForm->createView()
486
                ]
487
            );
488
        }
489
        return $this->redirect(
490
            $this->generateUrl(
491
                'gateway_verify_second_factor_sms_verify_challenge',
492
                ['authenticationMode' => $authenticationMode]
493
            )
494
        );
495
    }
496
497
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
498
     * @Template
0 ignored issues
show
Coding Style introduced by
Tag @Template cannot be grouped with parameter tags in a doc comment
Loading history...
499
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 4 spaces but found 1
Loading history...
500
     * @param string $authenticationMode
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Superfluous parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 4 spaces but found 1
Loading history...
501
     * @return array|Response
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
Coding Style introduced by
Tag value for @return tag indented incorrectly; expected 3 spaces but found 1
Loading history...
502
     */
503
    public function verifySmsSecondFactorChallengeAction(Request $request)
504
    {
505
        if (!$request->get('authenticationMode', false)) {
506
            throw new RuntimeException('Unable to determine the authentication mode in the SMS challenge action');
507
        }
508
        $authenticationMode = $request->get('authenticationMode');
509
        $this->supportsAuthenticationMode($authenticationMode);
510
        $context = $this->getResponseContext($authenticationMode);
511
        $originalRequestId = $context->getInResponseTo();
512
513
        /** @var \Surfnet\SamlBundle\Monolog\SamlAuthenticationLogger $logger */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
514
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
515
516
        $selectedSecondFactor = $this->getSelectedSecondFactor($context, $logger);
517
518
        $command = new VerifyPossessionOfPhoneCommand();
519
        $form = $this->createForm(VerifySmsChallengeType::class, $command)->handleRequest($request);
520
        $cancelForm = $this->buildCancelAuthenticationForm($authenticationMode)->handleRequest($request);
521
522
        if ($form->isSubmitted() && $form->isValid()) {
523
            $logger->notice('Verifying input SMS challenge matches');
524
            $command->secondFactorId = $selectedSecondFactor;
525
            $verification = $this->getStepupService()->verifySmsChallenge($command);
526
527
            if ($verification->wasSuccessful()) {
528
                $this->getStepupService()->clearSmsVerificationState($selectedSecondFactor);
529
530
                $this->getResponseContext($authenticationMode)->markSecondFactorVerified();
531
                $this->getAuthenticationLogger()->logSecondFactorAuthentication($originalRequestId, $authenticationMode);
0 ignored issues
show
Bug introduced by
It seems like $originalRequestId can also be of type null; however, parameter $requestId of Surfnet\StepupGateway\Ga...dFactorAuthentication() does only seem to accept string, 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

531
                $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
532
533
                $logger->info(
534
                    sprintf(
535
                        'Marked Sms Second Factor "%s" as verified, forwarding to Saml Proxy to respond',
536
                        $selectedSecondFactor
537
                    )
538
                );
539
                return $this->forward($context->getResponseAction());
0 ignored issues
show
Bug introduced by
It seems like $context->getResponseAction() can also be of type null; however, parameter $controller of Symfony\Bundle\Framework...r\Controller::forward() does only seem to accept string, 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

539
                return $this->forward(/** @scrutinizer ignore-type */ $context->getResponseAction());
Loading history...
540
            } elseif ($verification->didOtpExpire()) {
541
                $logger->notice('SMS challenge expired');
542
                $form->addError(
543
                    new FormError($this->get('translator')->trans('gateway.form.send_sms_challenge.challenge_expired'))
544
                );
545
            } elseif ($verification->wasAttemptedTooManyTimes()) {
546
                $logger->notice('SMS challenge verification was attempted too many times');
547
                $form->addError(
548
                    new FormError($this->get('translator')->trans('gateway.form.send_sms_challenge.too_many_attempts'))
549
                );
550
            } else {
551
                $logger->notice('SMS challenge did not match');
552
                $form->addError(
553
                    new FormError(
554
                        $this->get('translator')->trans('gateway.form.send_sms_challenge.sms_challenge_incorrect')
555
                    )
556
                );
557
            }
558
        }
559
        return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
560
    }
561
562
    public function cancelAuthenticationAction()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function cancelAuthenticationAction()
Loading history...
563
    {
564
        return $this->forward('SurfnetStepupGatewayGatewayBundle:Gateway:sendAuthenticationCancelledByUser');
565
    }
566
567
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
568
     * @return \Surfnet\StepupGateway\GatewayBundle\Service\StepupAuthenticationService
569
     */
570
    private function getStepupService()
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::getStepupService" must be prefixed with an underscore
Loading history...
571
    {
572
        return $this->get('gateway.service.stepup_authentication');
573
    }
574
575
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $authenticationMode should have a doc-comment as per coding-style.
Loading history...
576
     * @return ResponseContext
577
     */
578
    private function getResponseContext($authenticationMode)
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::getResponseContext" must be prefixed with an underscore
Loading history...
579
    {
580
        switch ($authenticationMode) {
581
            case self::MODE_SFO:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
582
                return $this->get($this->get('gateway.proxy.sfo.state_handler')->getResponseContextServiceId());
583
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
584
            case self::MODE_SSO:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
585
                return $this->get($this->get('gateway.proxy.sso.state_handler')->getResponseContextServiceId());
586
                break;
587
        }
588
    }
589
590
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
591
     * @return \Surfnet\StepupGateway\GatewayBundle\Monolog\Logger\AuthenticationLogger
592
     */
593
    private function getAuthenticationLogger()
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::getAuthenticationLogger" must be prefixed with an underscore
Loading history...
594
    {
595
        return $this->get('gateway.authentication_logger');
596
    }
597
598
    private function getCookieService(): CookieService
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCookieService()
Loading history...
Coding Style introduced by
Private method name "SecondFactorController::getCookieService" must be prefixed with an underscore
Loading history...
599
    {
600
        return $this->get('gateway.service.sso_2fa_cookie');
601
    }
602
    private function getSecondFactorService(): SecondFactorService
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getSecondFactorService()
Loading history...
Coding Style introduced by
Private method name "SecondFactorController::getSecondFactorService" must be prefixed with an underscore
Loading history...
603
    {
604
        return $this->get('gateway.service.second_factor_service');
605
    }
606
607
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
608
     * @param ResponseContext $context
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
609
     * @param LoggerInterface $logger
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
610
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
611
     */
612
    private function getSelectedSecondFactor(ResponseContext $context, LoggerInterface $logger)
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::getSelectedSecondFactor" must be prefixed with an underscore
Loading history...
613
    {
614
        $selectedSecondFactor = $context->getSelectedSecondFactor();
615
616
        if (!$selectedSecondFactor) {
617
            $logger->error('Cannot verify possession of an unknown second factor');
618
619
            throw new BadRequestHttpException('Cannot verify possession of an unknown second factor.');
620
        }
621
622
        return $selectedSecondFactor;
623
    }
624
625
    private function selectAndRedirectTo(SecondFactor $secondFactor, ResponseContext $context, $authenticationMode)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function selectAndRedirectTo()
Loading history...
Coding Style introduced by
Private method name "SecondFactorController::selectAndRedirectTo" must be prefixed with an underscore
Loading history...
626
    {
627
        $context->saveSelectedSecondFactor($secondFactor);
628
629
        $this->getStepupService()->clearSmsVerificationState($secondFactor->secondFactorId);
630
631
        $secondFactorTypeService = $this->get('surfnet_stepup.service.second_factor_type');
632
        $secondFactorType = new SecondFactorType($secondFactor->secondFactorType);
633
634
        $route = 'gateway_verify_second_factor_';
635
        if ($secondFactorTypeService->isGssf($secondFactorType)) {
636
            $route .= 'gssf';
637
        } else {
638
            $route .= strtolower($secondFactor->secondFactorType);
639
        }
640
641
        return $this->redirect($this->generateUrl($route, ['authenticationMode' => $authenticationMode]));
642
    }
643
644
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
645
     * @param string $authenticationMode
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
646
     * @return FormInterface
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
647
     */
648
    private function buildCancelAuthenticationForm($authenticationMode)
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::buildCancelAuthenticationForm" must be prefixed with an underscore
Loading history...
649
    {
650
        $cancelFormAction = $this->generateUrl(
651
            'gateway_cancel_authentication',
652
            ['authenticationMode' => $authenticationMode]
653
        );
654
655
        return $this->createForm(
656
            CancelAuthenticationType::class,
657
            null,
658
            ['action' => $cancelFormAction]
659
        );
660
    }
661
662
    private function supportsAuthenticationMode($authenticationMode)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function supportsAuthenticationMode()
Loading history...
Coding Style introduced by
Private method name "SecondFactorController::supportsAuthenticationMode" must be prefixed with an underscore
Loading history...
663
    {
664
        if (!($authenticationMode === self::MODE_SSO || $authenticationMode === self::MODE_SFO)) {
665
            throw new InvalidArgumentException('Invalid authentication mode requested');
666
        }
667
    }
668
}
669