Completed
Push — feature/gssp-add-through-confi... ( dd4473...1f4d21 )
by
unknown
02:53
created

GssfController::getProvider()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
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\Registration;
20
21
use Exception;
22
use Surfnet\SamlBundle\Http\XMLResponse;
23
use Surfnet\SamlBundle\SAML2\AuthnRequestFactory;
24
use Surfnet\SamlBundle\SAML2\Response\Assertion\InResponseTo;
25
use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig;
26
use Surfnet\StepupSelfService\SelfServiceBundle\Controller\Controller;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
30
31
/**
32
 * Controls registration with Generic SAML Stepup Providers (GSSPs), yielding Generic SAML Second Factors (GSSFs).
33
 */
34
final class GssfController extends Controller
35
{
36
    /**
37
     * @param string $provider
38
     * @param Request $request
39
     * @return array|Response
40
     */
41
    public function initiateAction($provider, Request $request)
42
    {
43
        $this->assertSecondFactorEnabled($provider);
44
45
        return $this->renderInitiateForm($provider, $request->getLocale(), []);
46
    }
47
48
    /**
49
     * @param string $provider
50
     * @return array|Response
51
     */
52
    public function authenticateAction($provider)
53
    {
54
        $this->assertSecondFactorEnabled($provider);
55
56
        $provider = $this->getProvider($provider);
57
58
        $authnRequest = AuthnRequestFactory::createNewRequest(
59
            $provider->getServiceProvider(),
60
            $provider->getRemoteIdentityProvider()
61
        );
62
63
        $stateHandler = $provider->getStateHandler();
64
        $stateHandler->setRequestId($authnRequest->getRequestId());
65
66
        /** @var \Surfnet\SamlBundle\Http\RedirectBinding $redirectBinding */
67
        $redirectBinding = $this->get('surfnet_saml.http.redirect_binding');
68
69
        $this->getLogger()->notice(sprintf(
70
            'Sending AuthnRequest with request ID: "%s" to GSSP "%s" at "%s"',
71
            $authnRequest->getRequestId(),
72
            $provider->getName(),
73
            $provider->getRemoteIdentityProvider()->getSsoUrl()
74
        ));
75
76
        return $redirectBinding->createRedirectResponseFor($authnRequest);
77
    }
78
79
    /**
80
     * @param Request $httpRequest
81
     * @param string  $provider
82
     * @return array|Response
83
     */
84
    public function consumeAssertionAction(Request $httpRequest, $provider)
85
    {
86
        $this->assertSecondFactorEnabled($provider);
87
88
        $provider = $this->getProvider($provider);
89
90
        $this->get('logger')->notice(
91
            sprintf('Received GSSP "%s" SAMLResponse through Gateway, attempting to process', $provider->getName())
92
        );
93
94
        try {
95
            /** @var \Surfnet\SamlBundle\Http\PostBinding $postBinding */
96
            $postBinding = $this->get('surfnet_saml.http.post_binding');
97
            $assertion = $postBinding->processResponse(
98
                $httpRequest,
99
                $provider->getRemoteIdentityProvider(),
100
                $provider->getServiceProvider()
101
            );
102
        } catch (Exception $exception) {
103
            $provider->getStateHandler()->clear();
104
105
            $this->getLogger()->error(
106
                sprintf('Could not process received Response, error: "%s"', $exception->getMessage())
107
            );
108
109
            return $this->renderInitiateForm(
110
                $provider->getName(),
111
                $httpRequest->getLocale(),
112
                ['authenticationFailed' => true]
113
            );
114
        }
115
116
        $expectedResponseTo = $provider->getStateHandler()->getRequestId();
117
        $provider->getStateHandler()->clear();
118
119
        if (!InResponseTo::assertEquals($assertion, $expectedResponseTo)) {
120
            $this->getLogger()->critical(sprintf(
121
                'Received Response with unexpected InResponseTo, %s',
122
                ($expectedResponseTo ? 'expected "' . $expectedResponseTo . '"' : ' no response expected')
123
            ));
124
125
            return $this->renderInitiateForm(
126
                $provider->getName(),
127
                $httpRequest->getLocale(),
128
                ['authenticationFailed' => true]
129
            );
130
        }
131
132
        $this->get('logger')->notice(
133
            sprintf('Processed GSSP "%s" SAMLResponse received through Gateway successfully', $provider->getName())
134
        );
135
136
        /** @var \Surfnet\StepupSelfService\SelfServiceBundle\Service\GssfService $service */
137
        $service = $this->get('surfnet_stepup_self_service_self_service.service.gssf');
138
        /** @var \Surfnet\SamlBundle\SAML2\Attribute\AttributeDictionary $attributeDictionary */
139
        $attributeDictionary = $this->get('surfnet_saml.saml.attribute_dictionary');
140
        $gssfId = $attributeDictionary->translate($assertion)->getNameID();
141
142
        $secondFactorId = $service->provePossession($this->getIdentity()->id, $provider->getName(), $gssfId);
143
144
        if ($secondFactorId) {
145
            $this->getLogger()->notice('GSSF possession has been proven successfully');
146
147
            return $this->redirectToRoute(
148
                'ss_registration_email_verification_email_sent',
149
                ['secondFactorId' => $secondFactorId]
150
            );
151
        }
152
153
        $this->getLogger()->error('Unable to prove GSSF possession');
154
155
        return $this->renderInitiateForm(
156
            $provider->getName(),
157
            $httpRequest->getLocale(),
158
            ['proofOfPossessionFailed' => true]
159
        );
160
    }
161
162
    /**
163
     * @param string $provider
164
     * @return \Symfony\Component\HttpFoundation\Response
165
     */
166
    public function metadataAction($provider)
167
    {
168
        $this->assertSecondFactorEnabled($provider);
169
170
        $provider = $this->getProvider($provider);
171
172
        /** @var \Surfnet\SamlBundle\Metadata\MetadataFactory $factory */
173
        $factory = $this->get('gssp.provider.' . $provider->getName() . '.metadata.factory');
174
175
        return new XMLResponse($factory->generate());
176
    }
177
178
    /**
179
     * @param string $provider
180
     * @return \Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\Provider
181
     * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
182
     */
183
    private function getProvider($provider)
184
    {
185
        /** @var \Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ProviderRepository $providerRepository */
186
        $providerRepository = $this->get('gssp.provider_repository');
187
188
        if (!$providerRepository->has($provider)) {
189
            $this->get('logger')->info(sprintf('Requested GSSP "%s" does not exist or is not registered', $provider));
190
191
            throw new NotFoundHttpException('Requested provider does not exist');
192
        }
193
194
        return $providerRepository->get($provider);
195
    }
196
197
    /**
198
     * @return \Psr\Log\LoggerInterface
199
     */
200
    private function getLogger()
201
    {
202
        return $this->get('logger');
203
    }
204
205
    /**
206
     * @param string $provider
207
     * @param string $locale
208
     * @param array $parameters
209
     * @return Response
210
     */
211
    private function renderInitiateForm($provider, $locale, array $parameters = [])
212
    {
213
        /** @var ViewConfig $secondFactorConfig */
214
        $secondFactorConfig = $this->get("gssp.view_config.{$provider}");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $provider instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
215
        $secondFactorConfig->currentLanguage = $locale;
0 ignored issues
show
Documentation Bug introduced by
It seems like $locale of type string is incompatible with the declared type null of property $currentLanguage.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
216
217
        $form = $this->createForm(
218
            'ss_initiate_gssf',
219
            null,
220
            [
221
                'provider' => $provider,
222
                /** @Ignore from translation message extraction */
223
                'label' => $secondFactorConfig->getInitiateButton()
224
            ]
225
        );
226
        /** @var ViewConfig $secondFactorConfig */
227
        $templateParameters = array_merge(
228
            $parameters,
229
            ['form' => $form->createView(), 'provider' => $provider, 'secondFactorConfig' => $secondFactorConfig]
230
        );
231
        return $this->render(
232
            'SurfnetStepupSelfServiceSelfServiceBundle:Registration/Gssf:initiate.html.twig',
233
            $templateParameters
234
        );
235
    }
236
}
237