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