Completed
Push — remote-vetting ( 9b6a17...6d48a7 )
by Pieter van der
02:08 queued 10s
created

RemoteVettingController::remoteVetAction()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 4
nc 2
nop 3
1
<?php
2
/**
3
 * Copyright 2010 SURFnet B.V.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace Surfnet\StepupSelfService\SelfServiceBundle\Controller;
19
20
use Psr\Log\LoggerInterface;
21
use SAML2\Response\Exception\PreconditionNotMetException;
22
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
23
use Surfnet\StepupBundle\DateTime\RegistrationExpirationHelper;
24
use Surfnet\StepupSelfService\SelfServiceBundle\Command\RemoteVetCommand;
25
use Surfnet\StepupSelfService\SelfServiceBundle\Command\RemoteVetValidationCommand;
26
use Surfnet\StepupSelfService\SelfServiceBundle\Exception\InvalidRemoteVettingContextException;
27
use Surfnet\StepupSelfService\SelfServiceBundle\Exception\InvalidRemoteVettingStateException;
28
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\RemoteVetSecondFactorType;
29
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\RemoteVetValidationType;
30
use Surfnet\StepupSelfService\SelfServiceBundle\Security\Authentication\Token\SamlToken;
31
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Dto\AttributeListDto;
32
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Dto\RemoteVettingTokenDto;
33
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\RemoteVettingViewHelper;
34
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\SamlCalloutHelper;
35
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Value\FeedbackCollection;
36
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Value\ProcessId;
37
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVettingService;
38
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SecondFactorService;
39
use Symfony\Component\HttpFoundation\RedirectResponse;
40
use Symfony\Component\HttpFoundation\Request;
41
use Symfony\Component\HttpFoundation\Response;
42
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
43
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
44
45
/**
46
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Too much coupling dus to glue code nature of this controller.
47
 *                                                 Could be refactored later on
48
 */
49
class RemoteVettingController extends Controller
50
{
51
    /**
52
     * @var RemoteVettingService
53
     */
54
    private $remoteVettingService;
55
    /**
56
     * @var SamlCalloutHelper
57
     */
58
    private $samlCalloutHelper;
59
    /**
60
     * @var LoggerInterface
61
     */
62
    private $logger;
63
    /**
64
     * @var RegistrationExpirationHelper
65
     */
66
    private $expirationHelper;
67
    /**
68
     * @var SecondFactorService
69
     */
70
    private $secondFactorService;
71
    /**
72
     * @var RemoteVettingViewHelper
73
     */
74
    private $remoteVettingViewHelper;
75
76
    public function __construct(
77
        RemoteVettingService $remoteVettingService,
78
        RemoteVettingViewHelper $remoteVettingViewHelper,
79
        SecondFactorService $secondFactorService,
80
        SamlCalloutHelper $samlCalloutHelper,
81
        RegistrationExpirationHelper $expirationHelper,
82
        LoggerInterface $logger
83
    ) {
84
        $this->secondFactorService = $secondFactorService;
85
        $this->remoteVettingService = $remoteVettingService;
86
        $this->samlCalloutHelper = $samlCalloutHelper;
87
        $this->expirationHelper = $expirationHelper;
88
        $this->logger = $logger;
89
        $this->remoteVettingViewHelper = $remoteVettingViewHelper;
90
    }
91
92
    /**
93
     * @Template
94
     * @param Request $request
95
     * @param string $secondFactorId
96
     * @param string $identityProviderSlug
97
     * @return array|Response
98
     */
99
    public function remoteVetAction(Request $request, $secondFactorId, $identityProviderSlug)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
100
    {
101
        $identity = $this->getIdentity();
102
103
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
104
        if ($secondFactor === null ||
105
            $secondFactor->identityId != $identity->id ||
106
            $this->expirationHelper->hasExpired($secondFactor->registrationRequestedAt)
107
        ) {
108
            throw new NotFoundHttpException(
109
                sprintf("No %s second factor with id '%s' exists.", 'verified', $secondFactorId)
110
            );
111
        }
112
113
        $token = RemoteVettingTokenDto::create(
114
            $identity->id,
115
            $secondFactor->id
116
        );
117
118
        $this->remoteVettingService->start($identityProviderSlug, $token);
119
120
        return new RedirectResponse($this->samlCalloutHelper->createAuthnRequest($identityProviderSlug));
121
    }
122
123
    /**
124
     * @param Request $request
125
     * @return mixed
126
     */
127
    public function acsAction(Request $request)
128
    {
129
        $this->logger->info('Receiving response from the remote IdP');
130
131
        /** @var FlashBagInterface $flashBag */
132
        $flashBag = $this->get('session')->getFlashBag();
133
134
        $this->logger->info('Load the attributes from the saml response');
135
136
        try {
137
            $processId = $this->samlCalloutHelper->handleResponse($request, $this->remoteVettingService->getActiveIdentityProviderSlug());
138
        } catch (InvalidRemoteVettingStateException $e) {
139
            $this->logger->error($e->getMessage());
140
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
141
            return $this->redirectToRoute('ss_second_factor_list');
142
        } catch (PreconditionNotMetException $e) {
143
            $this->logger->error($e->getMessage());
144
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
145
            return $this->redirectToRoute('ss_second_factor_list');
146
        } catch (InvalidRemoteVettingContextException $e) {
147
            $this->logger->error($e->getMessage());
148
            return $this->redirectToRoute('ss_second_factor_list');
149
        }
150
151
        return $this->redirectToRoute('ss_second_factor_remote_vet_match', [
152
            'processId' => $processId->getProcessId(),
153
        ]);
154
155
        return $this->redirectToRoute('ss_second_factor_list');
0 ignored issues
show
Unused Code introduced by
return $this->redirectTo...s_second_factor_list'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
156
    }
157
158
    /**
159
     * @param Request $request
160
     * @param $processId
161
     * @return Response
162
     */
163
    public function remoteVetMatchAction(Request $request, $processId)
164
    {
165
        /** @var FlashBagInterface $flashBag */
166
        $flashBag = $this->get('session')->getFlashBag();
167
168
        /** @var SamlToken $samlToken */
169
        $samlToken = $this->container->get('security.token_storage')->getToken();
170
171
        $localAttributes = AttributeListDto::fromAttributeSet($samlToken->getAttribute(SamlToken::ATTRIBUTE_SET));
172
173
        $matches = $this->remoteVettingService->getAttributeMatchCollection($localAttributes);
174
        $command = new RemoteVetValidationCommand($matches, new FeedbackCollection());
175
176
        try {
177
            $form = $this->createForm(RemoteVetValidationType::class, $command)->handleRequest($request);
178
            if ($form->isSubmitted() && $form->isValid()) {
179
180
                /** @var RemoteVetValidationCommand $command */
181
                $command = $form->getData();
182
183
                $token =  $this->remoteVettingService->done(
184
                    ProcessId::create($processId),
185
                    $this->getIdentity(),
186
                    $localAttributes,
187
                    $command->matches,
188
                    $command->feedback
189
                );
190
191
                $command = new RemoteVetCommand();
192
                $command->identity = $token->getIdentityId();
193
                $command->secondFactor = $token->getSecondFactorId();
194
195
                if ($this->secondFactorService->remoteVet($command)) {
196
                    $flashBag->add('success', 'ss.second_factor.revoke.alert.remote_vetting_successful');
197
                } else {
198
                    $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
199
                }
200
201
                return $this->redirectToRoute('ss_second_factor_list');
202
            }
203
            
204
            $provider = $this->remoteVettingViewHelper->getIdentityProvider($this->remoteVettingService->getActiveIdentityProviderSlug());
205
206
            return $this->render('SurfnetStepupSelfServiceSelfServiceBundle:remote_vetting:validation.html.twig', [
207
                'provider' => $provider,
208
                'identity' => $this->getIdentity(),
209
                'form' => $form->createView(),
210
            ]);
211
        } catch (InvalidRemoteVettingStateException $e) {
212
            $this->logger->error($e->getMessage());
213
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
214
            return $this->redirectToRoute('ss_second_factor_list');
215
        } catch (InvalidRemoteVettingContextException $e) {
216
            $this->logger->error($e->getMessage());
217
            return $this->redirectToRoute('ss_second_factor_list');
218
        }
219
    }
220
}
221