Passed
Pull Request — main (#308)
by Paul
16:02 queued 07:12
created

GssfController::consumeAssertion()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 84
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 50
nc 6
nop 2
dl 0
loc 84
rs 8.4686
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Copyright 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 Surfnet\SamlBundle\Http\XMLResponse;
23
use Surfnet\SamlBundle\SAML2\AuthnRequestFactory;
24
use Surfnet\SamlBundle\SAML2\Response\Assertion\InResponseTo;
25
use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\Provider;
26
use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig;
27
use Surfnet\StepupSelfService\SelfServiceBundle\Controller\Controller;
28
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\StatusGssfType;
29
use Symfony\Component\HttpFoundation\Request;
30
use Symfony\Component\HttpFoundation\Response;
31
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
32
use Symfony\Component\Routing\Annotation\Route;
33
34
/**
35
 * Controls registration with Generic SAML Stepup Providers (GSSPs), yielding Generic SAML Second Factors (GSSFs).
36
 */
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...
37
final class GssfController extends Controller
38
{
39
    /**
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...
40
     * Render the status form.
41
     *
42
     * This action has two parameters:
43
     *
44
     * - authenticationFailed (default false), will trigger an error message
45
     *   and is used when a SAML failure response was received, for example
46
     *   when the users cancelled the registration
47
     *
48
     * - proofOfPossessionFailed (default false), will trigger an error message
49
     *   when possession was not proven, but the SAML response was successful
50
     *
51
     * @return array|Response
52
     */
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
53
    #[Route(
54
        path: '/registration/gssf/{provider}/status',
55
        name: 'ss_registration_gssf_status_report',
56
        defaults: ['authenticationFailed' => false, 'proofOfPossessionFailed'=> false ],
57
        methods: ['GET'],
58
    )]
59
60
    public function status(Request $request, string $provider): \Symfony\Component\HttpFoundation\Response
61
    {
62
        $this->assertSecondFactorEnabled($provider);
63
64
        return $this->renderStatusForm(
65
            $provider,
66
            [
67
                'authenticationFailed' => (bool) $request->query->get('authenticationFailed'),
68
                'proofOfPossessionFailed' => (bool) $request->query->get('proofOfPossessionFailed'),
69
            ]
70
        );
71
    }
72
73
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
74
     * @param string $provider
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...
75
     * @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...
76
     */
77
    #[Route(
78
        path: '/registration/gssf/{provider}/authenticate',
79
        name: 'ss_registration_gssf_authenticate',
80
        methods: ['POST'],
81
    )]
82
    public function authenticate($provider)
83
    {
84
        $this->assertSecondFactorEnabled($provider);
85
86
        $provider = $this->getProvider($provider);
87
88
        $authnRequest = AuthnRequestFactory::createNewRequest(
89
            $provider->getServiceProvider(),
90
            $provider->getRemoteIdentityProvider()
91
        );
92
93
        $attributeService = $this->get('surfnet_stepup_self_service_self_service.service.gsspuserattributes');
0 ignored issues
show
Bug introduced by
The method get() does not exist on Surfnet\StepupSelfServic...stration\GssfController. ( Ignorable by Annotation )

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

93
        /** @scrutinizer ignore-call */ 
94
        $attributeService = $this->get('surfnet_stepup_self_service_self_service.service.gsspuserattributes');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
94
        $attributeService->addGsspUserAttributes(
95
            $authnRequest,
96
            $provider,
97
            $this->get('security.token_storage')->getToken()->getUser()
98
        );
99
        $stateHandler = $provider->getStateHandler();
100
        $stateHandler->setRequestId($authnRequest->getRequestId());
101
102
        /** @var \Surfnet\SamlBundle\Http\RedirectBinding $redirectBinding */
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...
103
        $redirectBinding = $this->get('surfnet_saml.http.redirect_binding');
104
105
        $this->getLogger()->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...
106
            'Sending AuthnRequest with request ID: "%s" to GSSP "%s" at "%s"',
107
            $authnRequest->getRequestId(),
108
            $provider->getName(),
109
            $provider->getRemoteIdentityProvider()->getSsoUrl()
110
        ));
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...
111
112
        return $redirectBinding->createRedirectResponseFor($authnRequest);
0 ignored issues
show
Bug introduced by
The method createRedirectResponseFor() does not exist on Surfnet\SamlBundle\Http\RedirectBinding. ( Ignorable by Annotation )

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

112
        return $redirectBinding->/** @scrutinizer ignore-call */ createRedirectResponseFor($authnRequest);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
113
    }
114
115
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $httpRequest should have a doc-comment as per coding-style.
Loading history...
116
     * @param string  $provider
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter type; 2 found
Loading history...
Coding Style introduced by
Doc comment for parameter $provider does not match actual variable name $httpRequest
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
117
     * @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...
118
     */
119
    #[Route(
120
        path: '/registration/gssf/{provider}/consume-assertion',
121
        name: 'ss_registration_gssf_consume_assertion',
122
        methods: ['POST'],
123
    )]
124
    public function consumeAssertion(Request $httpRequest, $provider)
125
    {
126
        $this->assertSecondFactorEnabled($provider);
127
128
        $provider = $this->getProvider($provider);
129
130
        $this->get('logger')->notice(
131
            sprintf('Received GSSP "%s" SAMLResponse through Gateway, attempting to process', $provider->getName())
132
        );
133
134
        try {
135
            /** @var \Surfnet\SamlBundle\Http\PostBinding $postBinding */
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...
136
            $postBinding = $this->get('surfnet_saml.http.post_binding');
137
            $assertion = $postBinding->processResponse(
138
                $httpRequest,
139
                $provider->getRemoteIdentityProvider(),
140
                $provider->getServiceProvider()
141
            );
142
        } catch (Exception $exception) {
143
            $provider->getStateHandler()->clear();
144
145
            $this->getLogger()->error(
146
                sprintf('Could not process received Response, error: "%s"', $exception->getMessage())
147
            );
148
149
            return $this->redirectToStatusReportForm(
150
                $provider,
151
                ['authenticationFailed' => true]
152
            );
153
        }
154
155
        $expectedResponseTo = $provider->getStateHandler()->getRequestId();
156
        $provider->getStateHandler()->clear();
157
158
        if (!InResponseTo::assertEquals($assertion, $expectedResponseTo)) {
159
            $this->getLogger()->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...
160
                'Received Response with unexpected InResponseTo, %s',
161
                ($expectedResponseTo ? 'expected "' . $expectedResponseTo . '"' : ' no response expected')
162
            ));
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...
163
164
            return $this->redirectToStatusReportForm(
165
                $provider,
166
                ['authenticationFailed' => true]
167
            );
168
        }
169
170
        $this->get('logger')->notice(
171
            sprintf('Processed GSSP "%s" SAMLResponse received through Gateway successfully', $provider->getName())
172
        );
173
174
        /** @var \Surfnet\StepupSelfService\SelfServiceBundle\Service\GssfService $service */
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
        $service = $this->get('surfnet_stepup_self_service_self_service.service.gssf');
176
        /** @var \Surfnet\SamlBundle\SAML2\Attribute\AttributeDictionary $attributeDictionary */
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...
177
        $attributeDictionary = $this->get('surfnet_saml.saml.attribute_dictionary');
178
        $gssfId = $attributeDictionary->translate($assertion)->getNameID();
179
180
        $secondFactorId = $service->provePossession($this->getIdentity()->id, $provider->getName(), $gssfId);
181
182
        if ($secondFactorId) {
183
            $this->getLogger()->notice('GSSF possession has been proven successfully');
184
185
            if ($this->emailVerificationIsRequired()) {
186
                return $this->redirectToRoute(
187
                    'ss_registration_email_verification_email_sent',
188
                    ['secondFactorId' => $secondFactorId]
189
                );
190
            } else {
191
                return $this->redirectToRoute(
192
                    'ss_second_factor_vetting_types',
193
                    ['secondFactorId' => $secondFactorId]
194
                );
195
            }
196
        }
197
198
        $this->getLogger()->error('Unable to prove GSSF possession');
199
200
        return $this->redirectToStatusReportForm(
201
            $provider,
202
            ['proofOfPossessionFailed' => true]
203
        );
204
    }
205
206
    private function redirectToStatusReportForm(Provider $provider, array $options): \Symfony\Component\HttpFoundation\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...
207
    {
208
        return $this->redirectToRoute(
209
            'ss_registration_gssf_status_report',
210
            $options + [
211
                'provider' => $provider->getName(),
212
            ]
213
        );
214
    }
215
216
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
217
     * @param string $provider
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...
218
     * @return \Symfony\Component\HttpFoundation\Response
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
219
     */
220
    #[Route(
221
        path: '/registration/gssf/{provider}/metadata',
222
        name: 'ss_registration_gssf_saml_metadata',
223
        methods: ['GET'],
224
    )]
225
    public function metadata($provider): \Surfnet\SamlBundle\Http\XMLResponse
226
    {
227
        $this->assertSecondFactorEnabled($provider);
228
229
        $provider = $this->getProvider($provider);
230
231
        /** @var \Surfnet\SamlBundle\Metadata\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...
232
        $factory = $this->get('gssp.provider.' . $provider->getName() . '.metadata.factory');
233
234
        return new XMLResponse($factory->generate());
235
    }
236
237
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
238
     * @param string $provider
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...
239
     * @return \Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\Provider
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
240
     * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
241
     */
242
    private function getProvider($provider)
0 ignored issues
show
Coding Style introduced by
Private method name "GssfController::getProvider" must be prefixed with an underscore
Loading history...
243
    {
244
        /** @var \Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ProviderRepository $providerRepository */
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...
245
        $providerRepository = $this->get('gssp.provider_repository');
246
247
        if (!$providerRepository->has($provider)) {
248
            $this->get('logger')->info(sprintf('Requested GSSP "%s" does not exist or is not registered', $provider));
249
250
            throw new NotFoundHttpException('Requested provider does not exist');
251
        }
252
253
        return $providerRepository->get($provider);
254
    }
255
256
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
257
     * @return \Psr\Log\LoggerInterface
258
     */
259
    private function getLogger()
0 ignored issues
show
Coding Style introduced by
Private method name "GssfController::getLogger" must be prefixed with an underscore
Loading history...
260
    {
261
        return $this->get('logger');
262
    }
263
264
    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...
265
    {
266
        /** @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...
267
        $secondFactorConfig = $this->get("gssp.view_config.{$provider}");
268
269
        $form = $this->createForm(
270
            StatusGssfType::class,
271
            null,
272
            [
273
                'provider' => $provider,
274
                /** @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...
275
                'label' => $secondFactorConfig->getInitiateButton()
276
            ]
277
        );
278
        /** @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...
279
        $templateParameters = array_merge(
280
            $parameters,
281
            [
282
                'form' => $form->createView(),
283
                'provider' => $provider,
284
                'secondFactorConfig' => $secondFactorConfig,
285
                'verifyEmail' => $this->emailVerificationIsRequired(),
286
            ]
287
        );
288
        return $this->render(
289
            'SurfnetStepupSelfServiceSelfServiceBundle:registration/gssf:status.html.twig',
290
            $templateParameters
291
        );
292
    }
293
}
294