Completed
Pull Request — develop (#93)
by Boy
04:06
created

SecondFactorOnlyController::respondAction()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 62
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 62
rs 8.9167
cc 4
eloc 37
nc 4
nop 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
 */
18
19
namespace Surfnet\StepupGateway\SecondFactorOnlyBundle\Controller;
20
21
use Exception;
22
use Psr\Log\LoggerInterface;
23
use Surfnet\SamlBundle\SAML2\AuthnRequest;
24
use Surfnet\StepupBundle\Value\Loa;
25
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Saml\ResponseFactory;
26
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Service\LoaAliasLookupService;
27
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
28
use Symfony\Component\HttpFoundation\Request;
29
use Symfony\Component\HttpFoundation\Response;
30
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
31
32
class SecondFactorOnlyController extends Controller
33
{
34
    const RESPONSE_CONTEXT_SERVICE_ID = 'second_factor_only.response_context';
35
36
    /**
37
     * @param Request $httpRequest
38
     * @return Response
39
     */
40
    public function ssoAction(Request $httpRequest)
41
    {
42
        $logger = $this->get('logger');
43
44
        if (!$this->getParameter('second_factor_only')) {
45
            $logger->notice(sprintf(
46
                'Access to %s denied, second_factor_only parameter set to false.',
47
                __METHOD__
48
            ));
49
            throw $this->createAccessDeniedException('Second Factor Only feature disabled');
50
        }
51
52
        $logger->notice(
53
            'Received AuthnRequest on second-factor-only endpoint, started processing'
54
        );
55
56
        /** @var \Surfnet\SamlBundle\Http\RedirectBinding $redirectBinding */
57
        $redirectBinding = $this->get('second_factor_only.http.redirect_binding');
58
59
        try {
60
            $originalRequest = $redirectBinding->processSignedRequest($httpRequest);
61
        } catch (Exception $e) {
62
            $logger->critical(sprintf('Could not process Request, error: "%s"', $e->getMessage()));
63
64
            return $this->render(
65
                'SurfnetStepupGatewayGatewayBundle:Gateway:unrecoverableError.html.twig'
66
            );
67
        }
68
69
        $originalRequestId = $originalRequest->getRequestId();
70
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
71
        $logger->notice(sprintf(
72
            'AuthnRequest processing complete, received AuthnRequest from "%s", request ID: "%s"',
73
            $originalRequest->getServiceProvider(),
74
            $originalRequest->getRequestId()
75
        ));
76
77
        $stateHandler = $this->get('gateway.proxy.state_handler');
78
79
        $stateHandler
80
            ->setRequestId($originalRequestId)
81
            ->setRequestServiceProvider($originalRequest->getServiceProvider())
82
            ->setRelayState($httpRequest->get(AuthnRequest::PARAMETER_RELAY_STATE, ''))
83
            ->setResponseAction('SurfnetStepupGatewaySecondFactorOnlyBundle:SecondFactorOnly:respond')
84
            ->setResponseContextServiceId(static::RESPONSE_CONTEXT_SERVICE_ID);
85
86
        // Check if the NameID is provided and we may use it.
87
        $nameId = $originalRequest->getNameId();
88
        if (!$this->get('second_factor_only.validate_nameid')->with($logger)->validate($originalRequest->getServiceProvider(), $nameId)) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 138 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
89
            /** @var \Surfnet\StepupGateway\GatewayBundle\Service\ResponseRenderingService $responseRendering */
90
            $responseRendering = $this->get('second_factor_only.response_rendering');
91
            return $responseRendering->renderRequesterFailureResponse(
92
                $this->getResponseContext()
93
            );
94
        }
95
        $stateHandler->saveIdentityNameId($nameId);
96
97
        // Check if the requested Loa is provided and supported.
98
        $authnContextClassRef = $originalRequest->getAuthenticationContextClassRef();
99
        $loaId = $this->get('second_factor_only.validate_accr')->with($logger)->validate($authnContextClassRef);
100
        if (empty($loaId)) {
101
            /** @var \Surfnet\StepupGateway\GatewayBundle\Service\ResponseRenderingService $responseRendering */
102
            $responseRendering = $this->get('second_factor_only.response_rendering');
103
            return $responseRendering->renderRequesterFailureResponse(
104
                $this->getResponseContext()
105
            );
106
        }
107
        $stateHandler->setRequiredLoaIdentifier($loaId);
108
109
        $logger->notice(
110
            'Forwarding to second factor controller for loa determination and handling'
111
        );
112
        return $this->forward(
113
            'SurfnetStepupGatewayGatewayBundle:SecondFactor:selectSecondFactorForVerification'
114
        );
115
    }
116
117
    /**
118
     * @return Response
119
     */
120
    public function respondAction()
121
    {
122
        $responseContext = $this->getResponseContext();
123
        $originalRequestId = $responseContext->getInResponseTo();
124
125
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
126
127
        if (!$this->getParameter('second_factor_only')) {
128
            $logger->notice(sprintf(
129
                'Access to %s denied, second_factor_only parameter set to false.',
130
                __METHOD__
131
            ));
132
            throw $this->createAccessDeniedException('Second Factor Only feature disabled');
133
        }
134
135
        $logger->notice('Creating second-factor-only Response');
136
137
        $selectedSecondFactorUuid = $this->getResponseContext()->getSelectedSecondFactor();
138
        if (!$selectedSecondFactorUuid) {
139
            $logger->error(
140
                'Cannot verify possession of an unknown second factor'
141
            );
142
143
            throw new BadRequestHttpException('Cannot verify possession of an unknown second factor.');
144
        }
145
146
        if (!$responseContext->isSecondFactorVerified()) {
147
            $logger->error('Second factor was not verified');
148
            throw new BadRequestHttpException(
149
                'Cannot verify possession of an unknown second factor.'
150
            );
151
        }
152
153
        $secondFactor = $this->get('gateway.service.second_factor_service')
154
            ->findByUuid($selectedSecondFactorUuid);
155
156
        $grantedLoa = $this->get('surfnet_stepup.service.loa_resolution')
157
            ->getLoaByLevel($secondFactor->getLoaLevel());
158
159
        /** @var LoaAliasLookupService $loaAliasLookup */
160
        $loaAliasLookup = $this->get('second_factor_only.loa_alias_lookup');
161
        $authnContextClassRef = $loaAliasLookup->findAliasByLoa($grantedLoa);
162
163
        /** @var ResponseFactory $response_factory */
164
        $responseFactory = $this->get('second_factor_only.saml_response_factory');
165
        $response = $responseFactory->createSecondFactorOnlyResponse(
166
            $responseContext->getIdentityNameId(),
167
            $responseContext->getServiceProvider(),
168
            $authnContextClassRef
169
        );
170
171
        $responseContext->responseSent();
172
173
        $logger->notice(sprintf(
174
            'Responding to request "%s" with newly created response "%s"',
175
            $responseContext->getInResponseTo(),
176
            $response->getId()
177
        ));
178
179
        $responseRendering = $this->get('second_factor_only.response_rendering');
180
        return $responseRendering->renderResponse($responseContext, $response);
181
    }
182
183
    /**
184
     * @return \Surfnet\StepupGateway\GatewayBundle\Saml\ResponseContext
185
     */
186
    public function getResponseContext()
187
    {
188
        return $this->get(static::RESPONSE_CONTEXT_SERVICE_ID);
189
    }
190
}
191