Completed
Pull Request — develop (#91)
by Boy
02:58
created

U2fController::verifyU2fAuthenticationAction()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 65
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 65
rs 8.8507
cc 4
eloc 42
nc 4
nop 1

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\GatewayBundle\Controller;
20
21
use Surfnet\StepupGateway\GatewayBundle\Saml\ResponseContext;
22
use Surfnet\StepupGateway\U2fVerificationBundle\Value\KeyHandle;
23
use Surfnet\StepupU2fBundle\Dto\SignResponse;
24
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
25
use Symfony\Component\HttpFoundation\Request;
26
use Symfony\Component\HttpFoundation\Response;
27
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
28
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
29
30
class U2fController extends Controller
31
{
32
    /**
33
     * @Template
34
     */
35
    public function initiateU2fAuthenticationAction()
36
    {
37
        /** @var ResponseContext $responseContext */
38
        $context = $this->get(
39
          $this->get('gateway.proxy.state_handler')->getResponseContextServiceId()
40
        );
41
        $originalRequestId = $context->getInResponseTo();
42
43
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
44
45
        $selectedSecondFactor = $this->get('gateway.service.require_selected_factor')
46
          ->requireSelectedSecondFactor($logger);
47
        $stepupService = $this->get('gateway.service.stepup_authentication');
48
49
        $cancelFormAction = $this->generateUrl('gateway_verify_second_factor_u2f_cancel_authentication');
50
        $cancelForm =
51
          $this->createForm('gateway_cancel_second_factor_verification', null, ['action' => $cancelFormAction]);
52
53
        $logger->notice('Verifying possession of U2F second factor, looking for registration matching key handle');
54
55
        $service = $this->get('surfnet_stepup_u2f_verification.service.u2f_verification');
56
        $keyHandle = new KeyHandle($stepupService->getSecondFactorIdentifier($selectedSecondFactor));
57
        $registration = $service->findRegistrationByKeyHandle($keyHandle);
58
59
        if ($registration === null) {
60
            $logger->critical(
61
              sprintf('No known registration for key handle of second factor "%s"', $selectedSecondFactor)
62
            );
63
            $this->addFlash('error', 'gateway.u2f.alert.unknown_registration');
64
65
            return ['authenticationFailed' => true, 'cancelForm' => $cancelForm->createView()];
66
        }
67
68
        $logger->notice('Creating sign request');
69
70
        $signRequest = $service->createSignRequest($registration);
71
        $signResponse = new SignResponse();
72
73
        $session = $this->get('gateway.session.u2f');
74
        $session->set('request', $signRequest);
75
76
        $formAction = $this->generateUrl('gateway_verify_second_factor_u2f_verify_authentication');
77
        $form = $this->createForm(
78
          'surfnet_stepup_u2f_verify_device_authentication',
79
          $signResponse,
80
          ['sign_request' => $signRequest, 'action' => $formAction]
81
        );
82
83
        return ['form' => $form->createView(), 'cancelForm' => $cancelForm->createView()];
84
    }
85
86
    /**
87
     * @Template("SurfnetStepupGatewayGatewayBundle:U2f:initiateU2fAuthentication.html.twig")
88
     *
89
     * @param Request $request
90
     * @return array|Response
91
     */
92
    public function verifyU2fAuthenticationAction(Request $request)
93
    {
94
        /** @var ResponseContext $responseContext */
95
        $context = $this->get(
96
          $this->get('gateway.proxy.state_handler')->getResponseContextServiceId()
97
        );
98
        $originalRequestId = $context->getInResponseTo();
99
100
        $logger = $this->get('surfnet_saml.logger')->forAuthentication($originalRequestId);
101
102
        $selectedSecondFactor = $this->get('gateway.service.require_selected_factor')
103
          ->requireSelectedSecondFactor($logger);
104
105
        $logger->notice('Received sign response from device');
106
107
        /** @var AttributeBagInterface $session */
108
        $session = $this->get('gateway.session.u2f');
109
        $signRequest = $session->get('request');
110
        $signResponse = new SignResponse();
111
112
        $formAction = $this->generateUrl('gateway_verify_second_factor_u2f_verify_authentication');
113
        $form = $this
114
          ->createForm(
115
            'surfnet_stepup_u2f_verify_device_authentication',
116
            $signResponse,
117
            ['sign_request' => $signRequest, 'action' => $formAction]
118
          )
119
          ->handleRequest($request);
120
121
        $cancelFormAction = $this->generateUrl('gateway_verify_second_factor_u2f_cancel_authentication');
122
        $cancelForm =
123
          $this->createForm('gateway_cancel_second_factor_verification', null, ['action' => $cancelFormAction]);
124
125
        if (!$form->isValid()) {
126
            $logger->error('U2F authentication verification could not be started because device send illegal data');
127
            $this->addFlash('error', 'gateway.u2f.alert.error');
128
129
            return ['authenticationFailed' => true, 'cancelForm' => $cancelForm->createView()];
130
        }
131
132
        $service = $this->get('surfnet_stepup_u2f_verification.service.u2f_verification');
133
        $result = $service->verifyAuthentication($signRequest, $signResponse);
134
135
        if ($result->wasSuccessful()) {
136
            $context->markSecondFactorVerified();
137
            $this->get('gateway.authentication_logger')->logSecondFactorAuthentication($originalRequestId);
138
139
            $logger->info(
140
              sprintf(
141
                'Marked U2F second factor "%s" as verified, forwarding to Saml Proxy to respond',
142
                $selectedSecondFactor
143
              )
144
            );
145
146
            return $this->forward($context->getResponseAction());
147
        } elseif ($result->didDeviceReportError()) {
148
            $logger->error('U2F device reported error during authentication');
149
            $this->addFlash('error', 'gateway.u2f.alert.device_reported_an_error');
150
        } else {
151
            $logger->error('U2F authentication verification failed');
152
            $this->addFlash('error', 'gateway.u2f.alert.error');
153
        }
154
155
        return ['authenticationFailed' => true, 'cancelForm' => $cancelForm->createView()];
156
    }
157
158
    public function cancelU2fAuthenticationAction()
159
    {
160
        return $this->forward(
161
          'SurfnetStepupGatewayGatewayBundle:Failure:sendAuthenticationCancelledByUser'
162
        );
163
    }
164
}
165