Passed
Push — master ( 5d1203...fec11d )
by Florent
01:52
created

RegistrationController::getUser()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 0
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2018 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace U2FAuthentication\Bundle\Controller;
13
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\HttpFoundation\JsonResponse;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
18
use Symfony\Component\HttpKernel\Exception\HttpException;
19
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
20
use U2FAuthentication\Bundle\Event\Events;
21
use U2FAuthentication\Bundle\Event\RegistrationRequestIssuedEvent;
22
use U2FAuthentication\Bundle\Event\RegistrationResponseInvalidEvent;
23
use U2FAuthentication\Bundle\Event\RegistrationResponseValidatedEvent;
24
use U2FAuthentication\Bundle\Model\HasRegisteredKeys;
25
use U2FAuthentication\RegistrationRequest;
26
use U2FAuthentication\RegistrationResponse;
27
28
class RegistrationController
29
{
30
    /**
31
     * @var string
32
     */
33
    private $applicationId;
34
35
    /**
36
     * @var TokenStorageInterface
37
     */
38
    private $tokenStorage;
39
40
    /**
41
     * @var array
42
     */
43
    private $issuerCertificates;
44
45
    /**
46
     * @var EventDispatcherInterface
47
     */
48
    private $eventDispatcher;
49
50
    /**
51
     * RegistrationController constructor.
52
     * @param EventDispatcherInterface $eventDispatcher
53
     * @param TokenStorageInterface    $tokenStorage
54
     * @param string                   $applicationId
55
     * @param array                    $issuerCertificates
56
     */
57
    public function __construct(EventDispatcherInterface $eventDispatcher, TokenStorageInterface $tokenStorage, string $applicationId, array $issuerCertificates)
58
    {
59
        $this->eventDispatcher = $eventDispatcher;
60
        $this->tokenStorage = $tokenStorage;
61
        $this->applicationId = $applicationId;
62
        $this->issuerCertificates = $issuerCertificates;
63
    }
64
65
    /**
66
     * @param Request $request
67
     *
68
     * @return JsonResponse
69
     */
70
    public function getRegistrationRequestAction(Request $request): JsonResponse
71
    {
72
        $user = $this->getUser();
73
        try {
74
            $registrationRequest = RegistrationRequest::create($this->applicationId);
75
            $request->getSession()->set('U2F_REGISTRATION_REQUEST', $registrationRequest);
76
            $this->eventDispatcher->dispatch(
77
                Events::U2F_REGISTRATION_REQUEST_ISSUED,
78
                new RegistrationRequestIssuedEvent($user, $registrationRequest)
79
            );
80
81
            return new JsonResponse($registrationRequest);
82
        } catch (\Exception $e) {
83
            throw new HttpException(500, 'An error occurred during the creation of the registration request.', $e);
84
        }
85
    }
86
87
    /**
88
     * @param Request $request
89
     *
90
     * @return JsonResponse
91
     */
92
    public function postRegistrationRequestAction(Request $request): JsonResponse
93
    {
94
        $user = $this->getUser();
95
        $registrationRequest = $request->getSession()->get('U2F_REGISTRATION_REQUEST');
96
        if (!$registrationRequest instanceof RegistrationRequest) {
97
            throw new HttpException(400, 'The registration request is missing');
98
        }
99
        $request->getSession()->remove('U2F_REGISTRATION_REQUEST');
100
101
        $data = $request->request->all();
102
        $registrationResponse = RegistrationResponse::create($data);
103
104
        if (!$registrationResponse->isValid($registrationRequest, $this->issuerCertificates)) {
105
            $this->eventDispatcher->dispatch(
106
                Events::U2F_REGISTRATION_RESPONSE_INVALID,
107
                new RegistrationResponseInvalidEvent($user, $registrationResponse)
108
            );
109
110
            throw new HttpException(400, 'The registration response is invalid');
111
        }
112
113
        $this->eventDispatcher->dispatch(
114
            Events::U2F_REGISTRATION_RESPONSE_VALIDATED,
115
            new RegistrationResponseValidatedEvent($user, $registrationResponse)
116
        );
117
118
        return new JsonResponse(['registered' => 'ok'], 204);
119
    }
120
121
    /**
122
     * @return HasRegisteredKeys
123
     */
124
    private function getUser(): HasRegisteredKeys
125
    {
126
        $token = $this->tokenStorage->getToken();
127
        if (null === $token) {
128
            throw new AccessDeniedHttpException('The user must be connected');
129
        }
130
        $user = $token->getUser();
131
        if (null === $user) {
132
            throw new AccessDeniedHttpException('The user must be connected');
133
        }
134
        if (!$user instanceof HasRegisteredKeys) {
135
            throw new AccessDeniedHttpException('The user does not support the U2F keys');
136
        }
137
138
        return $user;
139
    }
140
}
141