Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
49 | class SamlProxyController extends Controller |
||
50 | { |
||
51 | /** |
||
52 | * Proxy a GSSP authentication request to the remote GSSP SSO endpoint. |
||
53 | * |
||
54 | * The user is about to be sent to the remote GSSP application. An authn |
||
55 | * request was created in ::sendSecondFactorVerificationAuthnRequestAction() and this method |
||
56 | * proxies the authn request to the remote SSO URL. The remote application |
||
57 | * will send an assertion back to consumeAssertionAction(). |
||
58 | * |
||
59 | * @param string $provider |
||
60 | * @param Request $httpRequest |
||
61 | * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response |
||
62 | */ |
||
63 | public function singleSignOnAction($provider, Request $httpRequest) |
||
64 | { |
||
65 | $provider = $this->getProvider($provider); |
||
66 | |||
67 | $logger = $this->get('logger'); |
||
68 | $logger->notice('Received AuthnRequest, started processing'); |
||
69 | |||
70 | /** @var \Surfnet\SamlBundle\Http\RedirectBinding $redirectBinding */ |
||
71 | $redirectBinding = $this->get('surfnet_saml.http.redirect_binding'); |
||
72 | |||
73 | $originalRequest = $redirectBinding->processSignedRequest($httpRequest); |
||
74 | |||
75 | $originalRequestId = $originalRequest->getRequestId(); |
||
76 | $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId); |
||
77 | $logger->notice(sprintf( |
||
78 | 'AuthnRequest processing complete, received AuthnRequest from "%s", request ID: "%s"', |
||
79 | $originalRequest->getServiceProvider(), |
||
80 | $originalRequest->getRequestId() |
||
81 | )); |
||
82 | |||
83 | $logger->debug('Checking if SP "%s" is supported'); |
||
84 | /** |
||
85 | * @var \Surfnet\StepupGateway\SamlStepupProviderBundle\Provider\ConnectedServiceProviders $connectedServiceProviders |
||
|
|||
86 | */ |
||
87 | $connectedServiceProviders = $this->get('gssp.connected_service_providers'); |
||
88 | if (!$connectedServiceProviders->isConnected($originalRequest->getServiceProvider())) { |
||
89 | $logger->warning(sprintf( |
||
90 | 'Received AuthnRequest from SP "%s", while SP is not allowed to use this for SSO', |
||
91 | $originalRequest->getServiceProvider() |
||
92 | )); |
||
93 | |||
94 | throw new AccessDeniedHttpException(); |
||
95 | } |
||
96 | |||
97 | /** @var StateHandler $stateHandler */ |
||
98 | $stateHandler = $provider->getStateHandler(); |
||
99 | |||
100 | // Clear the state of the previous SSO action. Request data of |
||
101 | // previous SSO actions should not have any effect in subsequent SSO |
||
102 | // actions. |
||
103 | $stateHandler->clear(); |
||
104 | |||
105 | $stateHandler |
||
106 | ->setRequestId($originalRequestId) |
||
107 | ->setRequestServiceProvider($originalRequest->getServiceProvider()) |
||
108 | ->setRequestAssertionConsumerServiceUrl($originalRequest->getAssertionConsumerServiceURL()) |
||
109 | ->setRelayState($httpRequest->get(AuthnRequest::PARAMETER_RELAY_STATE, '')); |
||
110 | |||
111 | $proxyRequest = AuthnRequestFactory::createNewRequest( |
||
112 | $provider->getServiceProvider(), |
||
113 | $provider->getRemoteIdentityProvider() |
||
114 | ); |
||
115 | |||
116 | // if a Specific subject is given to authenticate we should proxy that and verify in the response |
||
117 | // that that subject indeed was authenticated |
||
118 | $nameId = $originalRequest->getNameId(); |
||
119 | if ($nameId) { |
||
120 | $proxyRequest->setSubject($nameId, $originalRequest->getNameIdFormat()); |
||
121 | $stateHandler->setSubject($nameId); |
||
122 | } |
||
123 | |||
124 | $proxyRequest->setScoping([$originalRequest->getServiceProvider()]); |
||
125 | $stateHandler->setGatewayRequestId($proxyRequest->getRequestId()); |
||
126 | |||
127 | $logger->notice(sprintf( |
||
128 | 'Sending Proxy AuthnRequest with request ID: "%s" for original AuthnRequest "%s" to GSSP "%s" at "%s"', |
||
129 | $proxyRequest->getRequestId(), |
||
130 | $originalRequest->getRequestId(), |
||
131 | $provider->getName(), |
||
132 | $provider->getRemoteIdentityProvider()->getSsoUrl() |
||
133 | )); |
||
134 | |||
135 | return $redirectBinding->createResponseFor($proxyRequest); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Start a GSSP single sign-on. |
||
140 | * |
||
141 | * The user has selected a second factor token and the token happens to be |
||
142 | * a GSSP token. The SecondFactorController therefor did an internal |
||
143 | * redirect (see SecondFactorController::verifyGssfAction) to this method. |
||
144 | * |
||
145 | * In this method, an authn request is created. This authn request is not |
||
146 | * sent directly to the GSSP SSO URL, but proxied trough the gateway first |
||
147 | * (see SamlProxyController::ssoAction). |
||
148 | * |
||
149 | * @param $provider |
||
150 | * @param $subjectNameId |
||
151 | * @return \Symfony\Component\HttpFoundation\RedirectResponse |
||
152 | */ |
||
153 | public function sendSecondFactorVerificationAuthnRequestAction($provider, $subjectNameId) |
||
187 | |||
188 | /** |
||
189 | * Process an assertion received from the remote GSSP application. |
||
190 | * |
||
191 | * The GSSP application sent an assertion back to the gateway. When |
||
192 | * successful, the user is sent back to the |
||
193 | * SecondFactorController:gssfVerifiedAction. |
||
194 | * |
||
195 | * @param string $provider |
||
196 | * @param Request $httpRequest |
||
197 | * @return \Symfony\Component\HttpFoundation\Response |
||
198 | */ |
||
199 | public function consumeAssertionAction($provider, Request $httpRequest) |
||
289 | |||
290 | /** |
||
291 | * @param string $provider |
||
292 | * @return XMLResponse |
||
293 | */ |
||
294 | public function metadataAction($provider) |
||
303 | |||
304 | /** |
||
305 | * @param string $provider |
||
306 | * @return \Surfnet\StepupGateway\SamlStepupProviderBundle\Provider\Provider |
||
307 | */ |
||
308 | private function getProvider($provider) |
||
321 | |||
322 | /** |
||
323 | * @param StateHandler $stateHandler |
||
324 | * @return string |
||
325 | */ |
||
326 | private function getDestination(StateHandler $stateHandler) |
||
345 | |||
346 | /** |
||
347 | * @param string $view |
||
348 | * @param StateHandler $stateHandler |
||
349 | * @param SAMLResponse $response |
||
350 | * @return Response |
||
351 | */ |
||
352 | View Code Duplication | public function renderSamlResponse($view, StateHandler $stateHandler, SAMLResponse $response) |
|
365 | |||
366 | /** |
||
367 | * @param string $view |
||
368 | * @param array $parameters |
||
369 | * @param Response $response |
||
370 | * @return Response |
||
371 | */ |
||
372 | public function render($view, array $parameters = array(), Response $response = null) |
||
380 | |||
381 | /** |
||
382 | * @param SAMLResponse $response |
||
383 | * @return string |
||
384 | */ |
||
385 | private function getResponseAsXML(SAMLResponse $response) |
||
389 | |||
390 | /** |
||
391 | * Response that indicates that an error occurred in the responder (the gateway). Used to indicate that we could |
||
392 | * not process the response we received from the upstream GSSP |
||
393 | * |
||
394 | * @param Provider $provider |
||
395 | * @param string $destination |
||
396 | * @return SAMLResponse |
||
397 | */ |
||
398 | private function createResponseFailureResponse(Provider $provider, $destination) |
||
405 | |||
406 | /** |
||
407 | * Response that indicates that the authentication could not be performed correctly. In this context it means |
||
408 | * that the upstream GSSP did not responsd with the same NameID as we request to authenticate in the AuthnRequest |
||
409 | * |
||
410 | * @param Provider $provider |
||
411 | * @param string $destination |
||
412 | * @return SAMLResponse |
||
413 | */ |
||
414 | private function createAuthnFailedResponse(Provider $provider, $destination) |
||
424 | |||
425 | /** |
||
426 | * Creates a standard response with default status Code (success) |
||
427 | * |
||
428 | * @param Provider $provider |
||
429 | * @param string $destination |
||
430 | * @return SAMLResponse |
||
431 | */ |
||
432 | private function createResponse(Provider $provider, $destination) |
||
442 | |||
443 | /** |
||
444 | * @param string $serviceProvider |
||
445 | * @return \Surfnet\StepupGateway\GatewayBundle\Entity\ServiceProvider |
||
446 | */ |
||
447 | private function getServiceProvider($serviceProvider) |
||
455 | } |
||
456 |
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.