Passed
Push — feature/build-and-publish-test... ( c594c2...5abced )
by
unknown
18:44
created

GssfController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 9
dl 0
loc 16
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\StepupSelfService\SelfServiceBundle\Controller\Registration;
20
21
use Exception;
22
use Psr\Log\LoggerInterface;
23
use Surfnet\SamlBundle\Http\XMLResponse;
24
use Surfnet\SamlBundle\Metadata\MetadataFactory;
25
use Surfnet\SamlBundle\SAML2\Attribute\AttributeDictionary;
26
use Surfnet\SamlBundle\SAML2\AuthnRequestFactory;
27
use Surfnet\SamlBundle\SAML2\Response\Assertion\InResponseTo;
28
use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\Provider;
29
use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ProviderRepository;
30
use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig;
31
use Surfnet\StepupSelfService\SelfServiceBundle\Controller\Controller;
32
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\StatusGssfType;
33
use Surfnet\StepupSelfService\SelfServiceBundle\Service\GssfService;
0 ignored issues
show
Bug introduced by
The type Surfnet\StepupSelfServic...dle\Service\GssfService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use Surfnet\StepupSelfService\SelfServiceBundle\Service\GsspUserAttributeService;
0 ignored issues
show
Bug introduced by
The type Surfnet\StepupSelfServic...sspUserAttributeService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
use Surfnet\StepupSelfService\SelfServiceBundle\Service\InstitutionConfigurationOptionsService;
36
use Symfony\Component\HttpFoundation\RedirectResponse;
37
use Symfony\Component\HttpFoundation\Request;
38
use Symfony\Component\HttpFoundation\Response;
39
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
40
use Symfony\Component\Routing\Annotation\Route;
41
use Surfnet\SamlBundle\Http\RedirectBinding;
42
use \Surfnet\SamlBundle\Http\PostBinding;
0 ignored issues
show
Bug introduced by
The type \Surfnet\SamlBundle\Http\PostBinding was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
43
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
44
45
46
/**
47
 * Controls registration with Generic SAML Stepup Providers (GSSPs), yielding Generic SAML Second Factors (GSSFs).
48
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
49
final class GssfController extends Controller
50
{
51
    public function __construct(
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
52
        private readonly LoggerInterface       $logger,
53
        InstitutionConfigurationOptionsService $configurationOptionsService,
54
        private readonly ProviderRepository    $providerRepository,
55
        private readonly RedirectBinding       $redirectBinding,
56
        private readonly PostBinding           $postBinding,
57
        private GsspUserAttributeService      $gsspUserAttributeService,
58
        private TokenStorageInterface                $tokenStorage,
59
        private GssfService                   $gssfService,
60
        private AttributeDictionary $attributeDictionary,
61
0 ignored issues
show
Coding Style introduced by
Blank lines are not allowed in a multi-line function declaration
Loading history...
62
0 ignored issues
show
Coding Style introduced by
Blank lines are not allowed in a multi-line function declaration
Loading history...
63
        
0 ignored issues
show
Coding Style introduced by
Blank lines are not allowed in a multi-line function declaration
Loading history...
64
    )
65
    {
0 ignored issues
show
Coding Style introduced by
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
66
        parent::__construct($logger, $configurationOptionsService);
67
    }
68
69
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $request should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $provider should have a doc-comment as per coding-style.
Loading history...
70
     * Render the status form.
71
     *
72
     * This action has two parameters:
73
     *
74
     * - authenticationFailed (default false), will trigger an error message
75
     *   and is used when a SAML failure response was received, for example
76
     *   when the users cancelled the registration
77
     *
78
     * - proofOfPossessionFailed (default false), will trigger an error message
79
     *   when possession was not proven, but the SAML response was successful
80
     *
81
     * @return array|Response
82
     */
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
83
    #[Route(
84
        path: '/registration/gssf/{provider}/status',
85
        name: 'ss_registration_gssf_status_report',
86
        defaults: ['authenticationFailed' => false, 'proofOfPossessionFailed'=> false ],
87
        methods: ['GET'],
88
    )]
89
90
    public function status(Request $request, string $provider): \Symfony\Component\HttpFoundation\Response
91
    {
92
        $this->assertSecondFactorEnabled($provider);
93
94
        return $this->renderStatusForm(
95
            $provider,
96
            [
97
                'authenticationFailed' => (bool) $request->query->get('authenticationFailed'),
98
                'proofOfPossessionFailed' => (bool) $request->query->get('proofOfPossessionFailed'),
99
            ]
100
        );
101
    }
102
103
    #[Route(
104
        path: '/registration/gssf/{provider}/authenticate',
105
        name: 'ss_registration_gssf_authenticate',
106
        methods: ['POST'],
107
    )]
108
    public function authenticate(string $provider): array|Response
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function authenticate()
Loading history...
109
    {
110
        $this->assertSecondFactorEnabled($provider);
111
112
        $provider = $this->getProvider($provider);
113
114
        $authnRequest = AuthnRequestFactory::createNewRequest(
115
            $provider->getServiceProvider(),
116
            $provider->getRemoteIdentityProvider()
117
        );
118
119
        $this->gsspUserAttributeService->addGsspUserAttributes(
120
            $authnRequest,
121
            $provider,
122
            $this->getIdentity()
123
        );
124
        $stateHandler = $provider->getStateHandler();
125
        $stateHandler->setRequestId($authnRequest->getRequestId());
126
127
        $this->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...
128
            'Sending AuthnRequest with request ID: "%s" to GSSP "%s" at "%s"',
129
            $authnRequest->getRequestId(),
130
            $provider->getName(),
131
            $provider->getRemoteIdentityProvider()->getSsoUrl()
132
        ));
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...
133
134
        return $this->redirectBinding->createResponseFor($authnRequest);
135
    }
136
137
    #[Route(
138
        path: '/registration/gssf/{provider}/consume-assertion',
139
        name: 'ss_registration_gssf_consume_assertion',
140
        methods: ['POST'],
141
    )]
142
    public function consumeAssertion(Request $httpRequest, string $provider): array|Response
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function consumeAssertion()
Loading history...
143
    {
144
        $this->assertSecondFactorEnabled($provider);
145
146
        $provider = $this->getProvider($provider);
147
148
        $this->logger->notice(
149
            sprintf('Received GSSP "%s" SAMLResponse through Gateway, attempting to process', $provider->getName())
150
        );
151
152
        try {
153
            $assertion = $this->postBinding->processResponse(
154
                $httpRequest,
155
                $provider->getRemoteIdentityProvider(),
156
                $provider->getServiceProvider()
157
            );
158
        } catch (Exception $exception) {
159
            $provider->getStateHandler()->clear();
160
161
            $this->logger->error(
162
                sprintf('Could not process received Response, error: "%s"', $exception->getMessage())
163
            );
164
165
            return $this->redirectToStatusReportForm(
166
                $provider,
167
                ['authenticationFailed' => true]
168
            );
169
        }
170
171
        $expectedResponseTo = $provider->getStateHandler()->getRequestId();
172
        $provider->getStateHandler()->clear();
173
174
        if (!InResponseTo::assertEquals($assertion, $expectedResponseTo)) {
175
            $this->logger->critical(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...
176
                'Received Response with unexpected InResponseTo, %s',
177
                ($expectedResponseTo ? 'expected "' . $expectedResponseTo . '"' : ' no response expected')
178
            ));
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...
179
180
            return $this->redirectToStatusReportForm(
181
                $provider,
182
                ['authenticationFailed' => true]
183
            );
184
        }
185
186
        $this->logger->notice(
187
            sprintf('Processed GSSP "%s" SAMLResponse received through Gateway successfully', $provider->getName())
188
        );
189
190
        $gssfId = $this->attributeDictionary->translate($assertion)->getNameID();
191
192
        $secondFactorId = $this->gssfService->provePossession($this->getIdentity()->id, $provider->getName(), $gssfId);
193
194
        if ($secondFactorId) {
195
            $this->logger->notice('GSSF possession has been proven successfully');
196
197
            if ($this->emailVerificationIsRequired()) {
198
                return $this->redirectToRoute(
199
                    'ss_registration_email_verification_email_sent',
200
                    ['secondFactorId' => $secondFactorId]
201
                );
202
            } else {
203
                return $this->redirectToRoute(
204
                    'ss_second_factor_vetting_types',
205
                    ['secondFactorId' => $secondFactorId]
206
                );
207
            }
208
        }
209
210
        $this->logger->error('Unable to prove GSSF possession');
211
212
        return $this->redirectToStatusReportForm(
213
            $provider,
214
            ['proofOfPossessionFailed' => true]
215
        );
216
    }
217
218
    private function redirectToStatusReportForm(Provider $provider, array $options): RedirectResponse
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function redirectToStatusReportForm()
Loading history...
Coding Style introduced by
Private method name "GssfController::redirectToStatusReportForm" must be prefixed with an underscore
Loading history...
219
    {
220
        return $this->redirectToRoute(
221
            'ss_registration_gssf_status_report',
222
            $options + [
223
                'provider' => $provider->getName(),
224
            ]
225
        );
226
    }
227
228
    #[Route(
229
        path: '/registration/gssf/{provider}/metadata',
230
        name: 'ss_registration_gssf_saml_metadata',
231
        methods: ['GET'],
232
    )]
233
    public function metadata(string $provider): XMLResponse
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function metadata()
Loading history...
234
    {
235
        $this->assertSecondFactorEnabled($provider);
236
237
        $provider = $this->getProvider($provider);
238
239
        /** @var MetadataFactory $factory */
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...
240
        $factory = $this->container->get('gssp.provider.' . $provider->getName() . '.metadata.factory');
241
242
        return new XMLResponse($factory->generate());
243
    }
244
245
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $provider should have a doc-comment as per coding-style.
Loading history...
246
     * @throws NotFoundHttpException
247
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
248
    private function getProvider(string $provider): Provider
0 ignored issues
show
Coding Style introduced by
Private method name "GssfController::getProvider" must be prefixed with an underscore
Loading history...
249
    {
250
        if (!$this->providerRepository->has($provider)) {
251
            $this->logger->info(sprintf('Requested GSSP "%s" does not exist or is not registered', $provider));
252
253
            throw new NotFoundHttpException('Requested provider does not exist');
254
        }
255
256
        return $this->providerRepository->get($provider);
257
    }
258
259
    private function renderStatusForm(string $provider, array $parameters = []): Response
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function renderStatusForm()
Loading history...
Coding Style introduced by
Private method name "GssfController::renderStatusForm" must be prefixed with an underscore
Loading history...
260
    {
261
        /** @var ViewConfig $secondFactorConfig */
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...
262
        $secondFactorConfig = $this->container->get("gssp.view_config.{$provider}");
263
264
        $form = $this->createForm(
265
            StatusGssfType::class,
266
            null,
267
            [
268
                'provider' => $provider,
269
                /** @Ignore from translation message extraction */
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...
270
                'label' => $secondFactorConfig->getInitiateButton()
271
            ]
272
        );
273
        /** @var ViewConfig $secondFactorConfig */
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...
274
        $templateParameters = array_merge(
275
            $parameters,
276
            [
277
                'form' => $form->createView(),
278
                'provider' => $provider,
279
                'secondFactorConfig' => $secondFactorConfig,
280
                'verifyEmail' => $this->emailVerificationIsRequired(),
281
            ]
282
        );
283
        return $this->render(
284
            'registration/gssf/status.html.twig',
285
            $templateParameters
286
        );
287
    }
288
}
289