Passed
Pull Request — develop (#302)
by Peter
04:59
created

SecondFactorController::getSecondFactorService()   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 0
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('Skipping second factor authentication. Required LoA was met by the LoA recorded in the cookie');
115
                // We use the SF from the cookie as the SF that was used for authenticating the second factor authentication
116
                $secondFactor = $this->getSecondFactorService()->findByUuid($ssoCookie->secondFactorId());
117
                $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

117
                $this->getResponseContext($authenticationMode)->saveSelectedSecondFactor(/** @scrutinizer ignore-type */ $secondFactor);
Loading history...
118
                $this->getResponseContext($authenticationMode)->markSecondFactorVerified();
119
                $this->getResponseContext($authenticationMode)->markVerifiedBySsoOn2faCookie(
120
                    $this->getCookieService()->getCookieFingerprint($request)
121
                );
122
                $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

122
                $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
123
                return $this->forward($context->getResponseAction());
124
            }
125
        }
126
127
        $secondFactorCollection = $this
128
            ->getStepupService()
129
            ->determineViableSecondFactors(
130
                $context->getIdentityNameId(),
131
                $requiredLoa,
132
                $this->get('gateway.service.whitelist')
133
            );
134
        switch (count($secondFactorCollection)) {
135
            case 0:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
136
                $logger->notice('No second factors can give the determined Loa');
137
                return $this->forward(
138
                    'SurfnetStepupGatewayGatewayBundle:Gateway:sendLoaCannotBeGiven',
139
                    ['authenticationMode' => $authenticationMode]
140
                );
141
            case 1:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
142
                $secondFactor = $secondFactorCollection->first();
143
                $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...
144
                    'Found "%d" second factors, using second factor of type "%s"',
145
                    count($secondFactorCollection),
146
                    $secondFactor->secondFactorType
147
                ));
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...
148
                return $this->selectAndRedirectTo($secondFactor, $context, $authenticationMode);
149
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
150
                return $this->forward(
151
                    'SurfnetStepupGatewayGatewayBundle:SecondFactor:chooseSecondFactor',
152
                    ['authenticationMode' => $authenticationMode, 'secondFactors' => $secondFactorCollection]
153
                );
154
        }
155
    }
156
157
    /**
158
     * The main WAYG screen
159
     * - Shows the token selection screen if you own > 1 token
160
     * - Directly goes to SF auth when identity owns 1 token
161
     *
162
     * @Template
0 ignored issues
show
Coding Style introduced by
Tag @Template cannot be grouped with parameter tags in a doc comment
Loading history...
163
     * @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...
164
     * @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...
165
     * @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...
166
     * @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...
167
     */
168
    public function chooseSecondFactorAction(Request $request, $authenticationMode)
169
    {
170
        $this->supportsAuthenticationMode($authenticationMode);
171
        $context = $this->getResponseContext($authenticationMode);
172
        $originalRequestId = $context->getInResponseTo();
173
174
        /** @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...
175
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
176
        $logger->notice('Ask the user which one of his suitable second factor tokens to use...');
177
178
        try {
179
            // Retrieve all requirements to determine the required LoA
180
            $requestedLoa = $context->getRequiredLoa();
181
            $spConfiguredLoas = $context->getServiceProvider()->get('configuredLoas');
182
183
            $normalizedIdpSho = $context->getNormalizedSchacHomeOrganization();
184
            $normalizedUserSho = $this->getStepupService()->getNormalizedUserShoByIdentityNameId($context->getIdentityNameId());
185
186
            $requiredLoa = $this
187
                ->getStepupService()
188
                ->resolveHighestRequiredLoa(
189
                    $requestedLoa,
190
                    $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

190
                    /** @scrutinizer ignore-type */ $spConfiguredLoas,
Loading history...
191
                    $normalizedIdpSho,
192
                    $normalizedUserSho
193
                );
194
        } catch (LoaCannotBeGivenException $e) {
195
            // Log the message of the domain exception, this contains a meaningful message.
196
            $logger->notice($e->getMessage());
197
            return $this->forward('SurfnetStepupGatewayGatewayBundle:Gateway:sendLoaCannotBeGiven');
198
        }
199
200
        $logger->notice(sprintf('Determined that the required Loa is "%s"', $requiredLoa));
201
202
        $secondFactors = $this
203
            ->getStepupService()
204
            ->determineViableSecondFactors(
205
                $context->getIdentityNameId(),
206
                $requiredLoa,
207
                $this->get('gateway.service.whitelist')
208
            );
209
210
        $command = new ChooseSecondFactorCommand();
211
        $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...
212
213
        $form = $this
214
            ->createForm(
215
                ChooseSecondFactorType::class,
216
                $command,
217
                ['action' => $this->generateUrl('gateway_verify_second_factor_choose_second_factor', ['authenticationMode' => $authenticationMode])]
218
            )
219
            ->handleRequest($request);
220
        $cancelForm = $this->buildCancelAuthenticationForm($authenticationMode)->handleRequest($request);
221
222
        if ($form->isSubmitted() && $form->isValid()) {
223
            $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

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

346
        $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
347
        $context->markSecondFactorVerified();
348
349
        $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...
350
            'Marked GSSF "%s" as verified, forwarding to Gateway controller to respond',
351
            $selectedSecondFactor
352
        ));
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...
353
        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

353
        return $this->forward(/** @scrutinizer ignore-type */ $context->getResponseAction());
Loading history...
354
    }
355
356
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
357
     * @Template
0 ignored issues
show
Coding Style introduced by
Tag @Template cannot be grouped with parameter tags in a doc comment
Loading history...
358
     * @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...
359
     * @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...
360
     */
361
    public function verifyYubiKeySecondFactorAction(Request $request)
362
    {
363
        if (!$request->get('authenticationMode', false)) {
364
            throw new RuntimeException('Unable to determine the authentication mode in Yubikey verification action');
365
        }
366
        $authenticationMode = $request->get('authenticationMode');
367
        $this->supportsAuthenticationMode($authenticationMode);
368
        $context = $this->getResponseContext($authenticationMode);
369
        $originalRequestId = $context->getInResponseTo();
370
371
        /** @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...
372
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
373
374
        $selectedSecondFactor = $this->getSelectedSecondFactor($context, $logger);
375
376
        $logger->notice('Verifying possession of Yubikey second factor');
377
378
        $command = new VerifyYubikeyOtpCommand();
379
        $command->secondFactorId = $selectedSecondFactor;
380
381
        $form = $this->createForm(VerifyYubikeyOtpType::class, $command)->handleRequest($request);
382
        $cancelForm = $this->buildCancelAuthenticationForm($authenticationMode)->handleRequest($request);
383
384
        if ($form->isSubmitted()  && $form->isValid()) {
385
            $result = $this->getStepupService()->verifyYubikeyOtp($command);
386
            if ($result->didOtpVerificationFail()) {
387
                $form->addError(
388
                    new FormError($this->get('translator')->trans('gateway.form.verify_yubikey.otp_verification_failed'))
389
                );
390
391
                // OTP field is rendered empty in the template.
392
                return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
393
            } elseif (!$result->didPublicIdMatch()) {
394
                $form->addError(
395
                    new FormError($this->get('translator')->trans('gateway.form.verify_yubikey.public_id_mismatch'))
396
                );
397
398
                // OTP field is rendered empty in the template.
399
                return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
400
            }
401
402
            $this->getResponseContext($authenticationMode)->markSecondFactorVerified();
403
            $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

403
            $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
404
405
            $logger->info(
406
                sprintf(
407
                    'Marked Yubikey Second Factor "%s" as verified, forwarding to Saml Proxy to respond',
408
                    $selectedSecondFactor
409
                )
410
            );
411
            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

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

525
                $this->getAuthenticationLogger()->logSecondFactorAuthentication(/** @scrutinizer ignore-type */ $originalRequestId, $authenticationMode);
Loading history...
526
527
                $logger->info(
528
                    sprintf(
529
                        'Marked Sms Second Factor "%s" as verified, forwarding to Saml Proxy to respond',
530
                        $selectedSecondFactor
531
                    )
532
                );
533
                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

533
                return $this->forward(/** @scrutinizer ignore-type */ $context->getResponseAction());
Loading history...
534
            } elseif ($verification->didOtpExpire()) {
535
                $logger->notice('SMS challenge expired');
536
                $form->addError(
537
                    new FormError($this->get('translator')->trans('gateway.form.send_sms_challenge.challenge_expired'))
538
                );
539
            } elseif ($verification->wasAttemptedTooManyTimes()) {
540
                $logger->notice('SMS challenge verification was attempted too many times');
541
                $form->addError(
542
                    new FormError($this->get('translator')->trans('gateway.form.send_sms_challenge.too_many_attempts'))
543
                );
544
            } else {
545
                $logger->notice('SMS challenge did not match');
546
                $form->addError(
547
                    new FormError(
548
                        $this->get('translator')->trans('gateway.form.send_sms_challenge.sms_challenge_incorrect')
549
                    )
550
                );
551
            }
552
        }
553
        return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
554
    }
555
556
    public function cancelAuthenticationAction()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function cancelAuthenticationAction()
Loading history...
557
    {
558
        return $this->forward('SurfnetStepupGatewayGatewayBundle:Gateway:sendAuthenticationCancelledByUser');
559
    }
560
561
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
562
     * @return \Surfnet\StepupGateway\GatewayBundle\Service\StepupAuthenticationService
563
     */
564
    private function getStepupService()
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::getStepupService" must be prefixed with an underscore
Loading history...
565
    {
566
        return $this->get('gateway.service.stepup_authentication');
567
    }
568
569
    /**
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...
570
     * @return ResponseContext
571
     */
572
    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...
573
    {
574
        switch ($authenticationMode) {
575
            case self::MODE_SFO:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
576
                return $this->get($this->get('gateway.proxy.sfo.state_handler')->getResponseContextServiceId());
577
                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...
578
            case self::MODE_SSO:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
579
                return $this->get($this->get('gateway.proxy.sso.state_handler')->getResponseContextServiceId());
580
                break;
581
        }
582
    }
583
584
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
585
     * @return \Surfnet\StepupGateway\GatewayBundle\Monolog\Logger\AuthenticationLogger
586
     */
587
    private function getAuthenticationLogger()
0 ignored issues
show
Coding Style introduced by
Private method name "SecondFactorController::getAuthenticationLogger" must be prefixed with an underscore
Loading history...
588
    {
589
        return $this->get('gateway.authentication_logger');
590
    }
591
592
    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...
593
    {
594
        return $this->get('gateway.service.sso_2fa_cookie');
595
    }
596
    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...
597
    {
598
        return $this->get('gateway.service.second_factor_service');
599
    }
600
601
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
602
     * @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...
603
     * @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...
604
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
605
     */
606
    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...
607
    {
608
        $selectedSecondFactor = $context->getSelectedSecondFactor();
609
610
        if (!$selectedSecondFactor) {
611
            $logger->error('Cannot verify possession of an unknown second factor');
612
613
            throw new BadRequestHttpException('Cannot verify possession of an unknown second factor.');
614
        }
615
616
        return $selectedSecondFactor;
617
    }
618
619
    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...
620
    {
621
        $context->saveSelectedSecondFactor($secondFactor);
622
623
        $this->getStepupService()->clearSmsVerificationState($secondFactor->secondFactorId);
624
625
        $secondFactorTypeService = $this->get('surfnet_stepup.service.second_factor_type');
626
        $secondFactorType = new SecondFactorType($secondFactor->secondFactorType);
627
628
        $route = 'gateway_verify_second_factor_';
629
        if ($secondFactorTypeService->isGssf($secondFactorType)) {
630
            $route .= 'gssf';
631
        } else {
632
            $route .= strtolower($secondFactor->secondFactorType);
633
        }
634
635
        return $this->redirect($this->generateUrl($route, ['authenticationMode' => $authenticationMode]));
636
    }
637
638
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
639
     * @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...
640
     * @return FormInterface
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
641
     */
642
    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...
643
    {
644
        $cancelFormAction = $this->generateUrl(
645
            'gateway_cancel_authentication',
646
            ['authenticationMode' => $authenticationMode]
647
        );
648
649
        return $this->createForm(
650
            CancelAuthenticationType::class,
651
            null,
652
            ['action' => $cancelFormAction]
653
        );
654
    }
655
656
    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...
657
    {
658
        if (!($authenticationMode === self::MODE_SSO || $authenticationMode === self::MODE_SFO)) {
659
            throw new InvalidArgumentException('Invalid authentication mode requested');
660
        }
661
    }
662
}
663