Completed
Pull Request — develop (#227)
by Michiel
04:22 queued 02:14
created

SamlController::consumeAssertionAction()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 59
c 0
b 0
f 0
rs 8.5833
cc 5
nc 8
nop 1

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
 */
18
19
namespace Surfnet\StepupSelfService\SelfServiceBundle\Controller;
20
21
use Exception;
22
use Surfnet\SamlBundle\Http\XMLResponse;
23
use Surfnet\SamlBundle\SAML2\Response\Assertion\InResponseTo;
24
use Surfnet\StepupBundle\Value\Loa;
25
use Surfnet\StepupSelfService\SelfServiceBundle\Value\SelfVetRequestId;
26
use Symfony\Component\HttpFoundation\Request;
27
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
28
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
29
use Symfony\Component\Security\Core\Exception\AuthenticationException;
30
31
class SamlController extends Controller
32
{
33
    /**
34
     * A SelfService user is able to test it's token in this endpoint
35
     *
36
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
37
     * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
38
     * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException
39
     */
40
    public function testSecondFactorAction()
41
    {
42
        $logger = $this->get('logger');
43
        $logger->notice('Starting second factor test');
44
45
        $secondFactorService = $this->get('surfnet_stepup_self_service_self_service.service.second_factor');
46
        $loaResolutionService = $this->get('surfnet_stepup.service.loa_resolution');
47
        $identity = $this->getIdentity();
48
49
        $vettedSecondFactors = $secondFactorService->findVettedByIdentity($identity->id);
50
        if (!$vettedSecondFactors || $vettedSecondFactors->getTotalItems() === 0) {
51
            $logger->error(
52
                sprintf(
53
                    'Identity "%s" tried to test a second factor, but does not own a suitable vetted token.',
54
                    $identity->id
55
                )
56
            );
57
58
            throw new NotFoundHttpException();
59
        }
60
61
        $authenticationRequestFactory = $this->get('self_service.test_second_factor_authentication_request_factory');
62
63
        // By requesting LoA 2 any relevant token can be tested (LoA 2 and 3)
64
        $authenticationRequest = $authenticationRequestFactory->createSecondFactorTestRequest(
65
            $identity->nameId,
66
            $loaResolutionService->getLoaByLevel(Loa::LOA_2)
67
        );
68
69
        $this->get('session')->set('second_factor_test_request_id', $authenticationRequest->getRequestId());
70
71
        $samlLogger = $this->get('surfnet_saml.logger')->forAuthentication($authenticationRequest->getRequestId());
72
        $samlLogger->notice('Sending authentication request to the second factor test IDP');
73
74
        return $this->get('surfnet_saml.http.redirect_binding')->createRedirectResponseFor($authenticationRequest);
75
    }
76
77
    public function consumeAssertionAction(Request $httpRequest)
78
    {
79
        $logger = $this->get('logger');
80
81
        $session = $this->get('session');
82
        // The test authentication IdP is also used for self vetting, a different session id is
83
        // used to mark a self vet command
84
        if ($session->has(SelfVetController::SELF_VET_SESSION_ID)) {
85
            /** @var SelfVetRequestId $selfVetRequestId */
86
            $selfVetRequestId = $session->get('second_factor_self_vet_request_id');
87
            $secondFactorId = $selfVetRequestId->vettingSecondFactorId();
88
            return $this->forward(
89
                'SurfnetStepupSelfServiceSelfServiceBundle:SelfVet:consumeSelfVetAssertion',
90
                ['secondFactorId' => $secondFactorId]
91
            );
92
        }
93
        if (!$session->has('second_factor_test_request_id')) {
94
            $logger->error(
95
                'Received an authentication response for testing a second factor, but no second factor test response was expected'
96
            );
97
98
            throw new AccessDeniedHttpException('Did not expect an authentication response');
99
        }
100
101
        $logger->notice('Received an authentication response for testing a second factor');
102
103
        $initiatedRequestId = $session->get('second_factor_test_request_id');
104
105
        $samlLogger = $this->get('surfnet_saml.logger')->forAuthentication($initiatedRequestId);
106
107
        $session->remove('second_factor_test_request_id');
108
109
        $postBinding = $this->get('surfnet_saml.http.post_binding');
110
111
        try {
112
            $assertion = $postBinding->processResponse(
113
                $httpRequest,
114
                $this->get('self_service.second_factor_test_idp'),
115
                $this->get('surfnet_saml.hosted.service_provider')
116
            );
117
118
            if (!InResponseTo::assertEquals($assertion, $initiatedRequestId)) {
119
                $samlLogger->error(
120
                    sprintf(
121
                        'Expected a response to the request with ID "%s", but the SAMLResponse was a response to a different request',
122
                        $initiatedRequestId
123
                    )
124
                );
125
126
                throw new AuthenticationException('Unexpected InResponseTo in SAMLResponse');
127
            }
128
129
            $session->getFlashBag()->add('success', 'ss.test_second_factor.verification_successful');
130
        } catch (Exception $exception) {
131
            $session->getFlashBag()->add('error', 'ss.test_second_factor.verification_failed');
132
        }
133
134
        return $this->redirectToRoute('ss_second_factor_list');
135
    }
136
137
    public function metadataAction()
138
    {
139
        /** @var \Surfnet\SamlBundle\Metadata\MetadataFactory $metadataFactory */
140
        $metadataFactory = $this->get('surfnet_saml.metadata_factory');
141
142
        return new XMLResponse($metadataFactory->generate());
143
    }
144
}
145