Failed Conditions
Push — ng ( d45f3b...ebdbf6 )
by Florent
14:16 queued 05:32
created

AnnotationDriver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Bundle\Annotation;
15
16
use Doctrine\Common\Annotations\Reader;
17
use OAuth2Framework\Bundle\Annotation\Checker\CheckerInterface;
18
use OAuth2Framework\Bundle\Security\Authentication\Token\OAuth2Token;
19
use OAuth2Framework\Component\Response\OAuth2ResponseFactoryManager;
20
use OAuth2Framework\Component\Response\OAuth2ResponseInterface;
21
use OAuth2Framework\Component\TokenType\TokenTypeManager;
22
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
23
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
24
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
25
26
final class AnnotationDriver
27
{
28
    /**
29
     * @var Reader
30
     */
31
    private $reader;
32
33
    /**
34
     * @var TokenStorageInterface
35
     */
36
    private $tokenStorage;
37
38
    /**
39
     * @var CheckerInterface[]
40
     */
41
    private $checkers = [];
42
43
    /**
44
     * @var TokenTypeManager
45
     */
46
    private $tokenTypeManager;
47
48
    /**
49
     * @var OAuth2ResponseFactoryManager
50
     */
51
    private $oauth2ResponseFactoryManager;
52
53
    /**
54
     * AnnotationDriver constructor.
55
     *
56
     * @param Reader                       $reader
57
     * @param TokenStorageInterface        $tokenStorage
58
     * @param TokenTypeManager             $tokenTypeManager
59
     * @param OAuth2ResponseFactoryManager $oauth2ResponseFactoryManager
60
     */
61
    public function __construct(Reader $reader, TokenStorageInterface $tokenStorage, TokenTypeManager $tokenTypeManager, OAuth2ResponseFactoryManager $oauth2ResponseFactoryManager)
62
    {
63
        $this->reader = $reader;
64
        $this->tokenStorage = $tokenStorage;
65
        $this->tokenTypeManager = $tokenTypeManager;
66
        $this->oauth2ResponseFactoryManager = $oauth2ResponseFactoryManager;
67
    }
68
69
    /**
70
     * @param CheckerInterface $checker
71
     *
72
     * @return AnnotationDriver
73
     */
74
    public function addChecker(CheckerInterface $checker): self
75
    {
76
        $this->checkers[] = $checker;
77
78
        return $this;
79
    }
80
81
    /**
82
     * @return CheckerInterface[]
83
     */
84
    public function getCheckers(): array
85
    {
86
        return $this->checkers;
87
    }
88
89
    public function onKernelController(FilterControllerEvent $event)
90
    {
91
        if (!is_array($controller = $event->getController())) {
92
            return;
93
        }
94
95
        $object = new \ReflectionObject($controller[0]);
96
        $method = $object->getMethod($controller[1]);
97
        $classConfigurations = $this->reader->getClassAnnotations($object);
98
        $methodConfigurations = $this->reader->getMethodAnnotations($method);
99
100
        foreach (array_merge($classConfigurations, $methodConfigurations) as $configuration) {
101
            if ($configuration instanceof OAuth2) {
102
                $token = $this->tokenStorage->getToken();
103
104
                if (!$token instanceof OAuth2Token) {
105
                    $this->createAuthenticationException($event, 'OAuth2 authentication required');
106
107
                    return;
108
                }
109
110
                foreach ($this->getCheckers() as $checker) {
111
                    $message = $checker->check($token, $configuration);
112
                    if (null !== $message) {
113
                        $this->createAccessDeniedException($event, $message);
114
115
                        return;
116
                    }
117
                }
118
            }
119
        }
120
    }
121
122
    /**
123
     * @param FilterControllerEvent $event
124
     * @param string                $message
125
     */
126
    private function createAuthenticationException(FilterControllerEvent &$event, $message)
127
    {
128
        $schemes = $this->tokenTypeManager->getSchemes();
129
        $response = $this->oauth2ResponseFactoryManager->getResponse(
130
            401,
131
            [
132
                'error' => OAuth2ResponseFactoryManager::ERROR_ACCESS_DENIED,
133
                'error_description' => $message,
134
                'schemes' => $schemes,
135
            ]
136
        );
137
138
        $this->updateFilterControllerEvent($event, $response);
139
    }
140
141
    /**
142
     * @param FilterControllerEvent $event
143
     * @param string                $message
144
     */
145
    private function createAccessDeniedException(FilterControllerEvent &$event, $message)
146
    {
147
        $response = $this->oauth2ResponseFactoryManager->getResponse(
148
            403,
149
            [
150
                'error' => OAuth2ResponseFactoryManager::ERROR_ACCESS_DENIED,
151
                'error_description' => $message,
152
            ]
153
        );
154
        $this->updateFilterControllerEvent($event, $response);
155
    }
156
157
    /**
158
     * @param FilterControllerEvent   $event
159
     * @param OAuth2ResponseInterface $response
160
     */
161
    private function updateFilterControllerEvent(FilterControllerEvent &$event, OAuth2ResponseInterface $response)
162
    {
163
        $event->setController(function () use ($response) {
164
            $factory = new HttpFoundationFactory();
165
            $response = $factory->createResponse($response->getResponse());
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $response, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
166
167
            return $response;
168
        });
169
    }
170
}
171