Completed
Push — feature/refactor-gateway-contr... ( 4996d0...48680d )
by
unknown
02:33
created

SecondFactorOnlyController::ssoAction()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 9.376
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
/**
4
 * Copyright 2018 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 Surfnet\StepupGateway\GatewayBundle\Exception\RequesterFailureException;
22
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Adfs\Exception\InvalidAdfsRequestException;
23
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Adfs\Exception\InvalidAdfsResponseException;
24
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Exception\InvalidSecondFactorMethodException;
25
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Service\Gateway\SecondFactorAdfsService;
26
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Service\Gateway\SecondFactorRespondService;
27
use Surfnet\StepupGateway\SecondFactorOnlyBundle\Service\Gateway\SecondFactorLoginService;
28
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
29
use Symfony\Component\HttpFoundation\Request;
30
use Symfony\Component\HttpFoundation\Response;
31
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
32
33
/**
34
 * Entry point for the Stepup SFO flow.
35
 *
36
 * See docs/GatewayState.md for a high-level diagram on how this controller
37
 * interacts with outside actors and other parts of Stepup.
38
 */
39
class SecondFactorOnlyController extends Controller
40
{
41
    /**
42
     * Receive an AuthnRequest from a service provider.
43
     *
44
     * This action will forward the user using an internal redirect to the
45
     * SecondFactorController to start the actual second factor verification.
46
     *
47
     * This action also detects if the request is made by ADFS, and tracks
48
     * some additional information in the session of the user in order to send
49
     * a non-standard response back to ADFS.
50
     *
51
     * @param Request $httpRequest
52
     * @return Response
53
     * @throws InvalidAdfsRequestException
54
     */
55
    public function ssoAction(Request $httpRequest)
56
    {
57
        $logger = $this->get('logger');
58
59
        if (!$this->getParameter('second_factor_only')) {
60
            $logger->notice('Access to ssoAction denied, second_factor_only parameter set to false.');
61
62
            throw $this->createAccessDeniedException('Second Factor Only feature is disabled');
63
        }
64
65
        $logger->notice('Received AuthnRequest on second-factor-only endpoint, started processing');
66
67
        $secondFactorLoginService = $this->getSecondFactorLoginService();
68
69
        // Handle binding
70
        $originalRequest = $secondFactorLoginService->handleBinding($httpRequest);
71
72
        // Transform ADFS request
73
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequest->getRequestId());
74
        $httpRequest = $this->getSecondFactorAdfsService()->handleAdfsRequest($logger, $httpRequest, $originalRequest);
75
76
        try {
77
            $secondFactorLoginService->singleSignOn($httpRequest, $originalRequest);
78
        } catch (RequesterFailureException $e) {
79
            /** @var \Surfnet\StepupGateway\GatewayBundle\Service\ResponseRenderingService $responseRendering */
80
            $responseRendering = $this->get('second_factor_only.response_rendering');
81
82
            return $responseRendering->renderRequesterFailureResponse($this->getResponseContext());
83
        }
84
85
        $logger->notice('Forwarding to second factor controller for loa determination and handling');
86
87
        return $this->forward('SurfnetStepupGatewayGatewayBundle:SecondFactor:selectSecondFactorForVerification');
88
    }
89
90
    /**
91
     * Send a SAML response back to the service provider.
92
     *
93
     * Second factor verification handled by SecondFactorController is
94
     * finished. The user was forwarded back to this action with an internal
95
     * redirect. This method sends a AuthnResponse back to the service
96
     * provider in response to the AuthnRequest received in ssoAction().
97
     *
98
     * @return Response
99
     * @throws InvalidAdfsResponseException
100
     */
101
    public function respondAction()
102
    {
103
104
        $responseContext = $this->getResponseContext();
105
        $originalRequestId = $responseContext->getInResponseTo();
106
107
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
108
109
        $responseRendering = $this->get('second_factor_only.response_rendering');
110
111
        if (!$this->getParameter('second_factor_only')) {
112
            $logger->notice(sprintf(
113
                'Access to %s denied, second_factor_only parameter set to false.',
114
                __METHOD__
115
            ));
116
            throw $this->createAccessDeniedException('Second Factor Only feature disabled');
117
        }
118
119
        try {
120
            $response = $this->getSecondFactorRespondService()->respondAction($responseContext);
0 ignored issues
show
Bug introduced by
The method respondAction() does not exist on Surfnet\StepupGateway\Se...ondFactorRespondService. Did you maybe mean respond()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
121
        } catch (InvalidSecondFactorMethodException $e) {
122
            throw new BadRequestHttpException($e->getMessage());
123
        }
124
125
        // Reset state
126
        $this->getSecondFactorRespondService()->respondReset($responseContext);
127
128
        // Handle adfs response
129
        $adfsParameters = $this->getSecondFactorAdfsService()->handleAdfsResponse($logger, $responseContext);
130
131
        if (!is_null($adfsParameters)) {
132
133
            $responseRendering = $this->get('second_factor_only.response_rendering');
134
            $xmlResponse = $responseRendering->getResponseAsXML($response);
135
136
            return $this->render(
137
                '@SurfnetStepupGatewaySecondFactorOnly/Adfs/consumeAssertion.html.twig',
138
                [
139
                    'acu' => $responseContext->getDestinationForAdfs(),
140
                    'samlResponse' => $xmlResponse,
141
                    'context' => $adfsParameters->getContext(),
142
                    'authMethod' => $adfsParameters->getAuthMethod(),
143
                ]
144
            );
145
        }
146
147
        return $responseRendering->renderResponse($responseContext, $response);
148
    }
149
150
    /**
151
     * @return \Surfnet\StepupGateway\GatewayBundle\Saml\ResponseContext
152
     */
153
    public function getResponseContext()
154
    {
155
        return $this->get('second_factor_only.response_context');
156
    }
157
158
    /**
159
     * @return SecondFactorLoginService
160
     */
161
    public function getSecondFactorLoginService()
162
    {
163
        return $this->get('second_factor_only.login_service');
164
    }
165
166
    /**
167
     * @return SecondFactorRespondService
168
     */
169
    public function getSecondFactorRespondService()
170
    {
171
        return $this->get('second_factor_only.respond_service');
172
    }
173
174
    /**
175
     * @return SecondFactorAdfsService
176
     */
177
    public function getSecondFactorAdfsService()
178
    {
179
        return $this->get('second_factor_only.adfs_service');
180
    }
181
}
182