Failed Conditions
Push — issue#702 ( 91bd46...0b5bf0 )
by Guilherme
19:37 queued 12:15
created

AuthorizeController   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 190
rs 10
c 0
b 0
f 0
wmc 22

9 Methods

Rating   Name   Duplication   Size   Complexity  
A authorizeAction() 0 3 1
A getClient() 0 10 2
A removeRemoteScope() 0 8 2
A handleAuthorizeAction() 0 21 2
A getOAuth2Server() 0 3 1
A handleAuthorize() 0 13 1
A getMetadata() 0 9 2
B shouldWarnUntrusted() 0 21 6
B validateAuthorizeAction() 0 59 5
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace LoginCidadao\OpenIDBundle\Controller;
12
13
use FOS\OAuthServerBundle\Event\OAuthEvent;
14
use LoginCidadao\CoreBundle\Model\PersonInterface;
15
use LoginCidadao\OpenIDBundle\Event\AuthorizationEvent;
16
use LoginCidadao\OpenIDBundle\LoginCidadaoOpenIDEvents;
17
use LoginCidadao\OpenIDBundle\Manager\ClientManager;
18
use LoginCidadao\OAuthBundle\Service\OrganizationService;
19
use LoginCidadao\OAuthBundle\Model\OrganizationInterface;
20
use LoginCidadao\OAuthBundle\Model\ClientInterface;
21
use OAuth2\Server;
22
use OAuth2\ServerBundle\Controller\AuthorizeController as BaseController;
23
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
24
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
25
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
26
use Symfony\Component\EventDispatcher\EventDispatcher;
27
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
28
use Symfony\Component\HttpFoundation\Request;
29
30
/**
31
 * Class AuthorizeController
32
 * @package LoginCidadao\OpenIDBundle\Controller
33
 * @codeCoverageIgnore
34
 */
35
class AuthorizeController extends BaseController
36
{
37
38
    /**
39
     * @Route("/openid/connect/authorize", name="_authorize_handle")
40
     * @Method({"POST"})
41
     */
42
    public function handleAuthorizeAction()
43
    {
44
        $request = $this->getRequest();
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Bundle\Framework...ontroller::getRequest() has been deprecated: since version 2.4, to be removed in 3.0. Ask Symfony to inject the Request object into your controller method instead by type hinting it in the method's signature. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

44
        $request = /** @scrutinizer ignore-deprecated */ $this->getRequest();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
45
        $implodedScope = implode(' ', $request->request->get('scope'));
46
        $request->request->set('scope', $implodedScope);
47
48
        $isAuthorized = $request->request->has('accepted')
49
            || !$request->request->has('rejected');
50
51
        $response = $this->handleAuthorize($this->getOAuth2Server(), $isAuthorized);
52
53
        $event = new OAuthEvent(
54
            $this->getUser(),
55
            $this->getClient($request), $isAuthorized
56
        );
57
58
        /** @var EventDispatcherInterface $dispatcher */
59
        $dispatcher = $this->get('event_dispatcher');
60
        $dispatcher->dispatch(OAuthEvent::POST_AUTHORIZATION_PROCESS, $event);
61
62
        return $response;
63
    }
64
65
    /**
66
     * Render the Authorization fragment
67
     *
68
     * @Template()
69
     *
70
     * @deprecated
71
     */
72
    public function authorizeAction()
73
    {
74
        throw new \RuntimeException('This class should not be used!');
75
    }
76
77
    /**
78
     * @Route("/openid/connect/authorize", name="_authorize_validate")
79
     * @Method({"GET"})
80
     * @Template("LoginCidadaoOpenIDBundle:Authorize:authorize.html.twig")
81
     */
82
    public function validateAuthorizeAction()
83
    {
84
        $request = $this->getRequest();
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Bundle\Framework...ontroller::getRequest() has been deprecated: since version 2.4, to be removed in 3.0. Ask Symfony to inject the Request object into your controller method instead by type hinting it in the method's signature. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

84
        $request = /** @scrutinizer ignore-deprecated */ $this->getRequest();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
85
        $client = $this->getClient($request);
86
87
        if (!$client instanceof \FOS\OAuthServerBundle\Model\ClientInterface) {
88
            return parent::validateAuthorizeAction();
89
        }
90
91
        /** @var PersonInterface $person */
92
        $person = $this->getUser();
93
94
        /** @var EventDispatcher $dispatcher */
95
        $dispatcher = $this->get('event_dispatcher');
96
97
        $event = new OAuthEvent($person, $client);
98
        $dispatcher->dispatch(OAuthEvent::PRE_AUTHORIZATION_PROCESS, $event);
99
100
        $isAuthorized = $event->isAuthorizedClient();
101
        $askConsent = $request->get('prompt', null) == 'consent';
102
103
        if ($isAuthorized && !$askConsent) {
104
            return $this->handleAuthorize($this->getOAuth2Server(), $isAuthorized);
105
        }
106
107
        $authEvent = new AuthorizationEvent($person, $client, $request->get('scope'));
108
        $dispatcher->dispatch(LoginCidadaoOpenIDEvents::NEW_AUTHORIZATION_REQUEST, $authEvent);
109
        $remoteClaims = $authEvent->getRemoteClaims();
110
111
        /** @var OrganizationService $organizationService */
112
        $organizationService = $this->get('organization');
113
        $warnUntrusted = $this->shouldWarnUntrusted($client);
114
        $metadata = $this->getMetadata($client);
115
        $organization = $organizationService->getOrganization($metadata);
116
117
        // Call the lib's original Controller
118
        $parentResponse = parent::validateAuthorizeAction();
119
        if (!is_array($parentResponse)) {
120
            return $parentResponse;
121
        }
122
        $parentResponse['scopes'] = $this->removeRemoteScope($parentResponse['scopes']);
123
124
        $response = array_merge([
125
            'qs' => [
126
                'client_id' => $client->getPublicId(),
127
                'scope' => $parentResponse['scopes'],
128
                'response_type' => $request->get('response_type'),
129
                'redirect_uri' => $request->get('redirect_uri'),
130
                'state' => $request->get('state'),
131
                'nonce' => $request->get('nonce'),
132
            ],
133
            'remoteClaims' => $remoteClaims,
134
            'client' => $client,
135
            'metadata' => $metadata,
136
            'organization' => $organization,
137
            'warnUntrusted' => $warnUntrusted,
138
        ], $parentResponse);
139
140
        return $response;
141
    }
142
143
    private function handleAuthorize(Server $server, $isAuthorized)
144
    {
145
        /** @var \OAuth2\Request $request */
146
        $request = $this->get('oauth2.request');
147
148
        /** @var \OAuth2\Response $response */
149
        $response = $this->get('oauth2.response');
150
151
        return $server->handleAuthorizeRequest(
152
            $request,
153
            $response,
154
            $isAuthorized,
155
            $this->getUser()->getId()
156
        );
157
    }
158
159
    private function getClient($fullId)
160
    {
161
        if ($fullId instanceof Request) {
162
            $fullId = $fullId->get('client_id');
163
        }
164
165
        /** @var ClientManager $clientManager */
166
        $clientManager = $this->get('lc.client_manager');
167
168
        return $clientManager->getClientById($fullId);
169
    }
170
171
    private function shouldWarnUntrusted(ClientInterface $client = null)
172
    {
173
        $warnUntrusted = $this->getParameter('warn_untrusted');
174
175
        if ($client) {
176
            $metadata = $this->getMetadata($client);
177
178
            if ($metadata && $metadata->getOrganization() instanceof OrganizationInterface) {
179
                $isTrusted = $metadata->getOrganization()->isTrusted();
180
            } else {
181
                $isTrusted = false;
182
            }
183
        } else {
184
            $isTrusted = false;
185
        }
186
187
        if ($isTrusted || !$warnUntrusted) {
188
            return false; // do not warn
189
        }
190
191
        return true; // warn
192
    }
193
194
    private function getMetadata(ClientInterface $client = null)
195
    {
196
        if (!$client) {
197
            return null;
198
        }
199
200
        $repo = $this->getDoctrine()->getRepository('LoginCidadaoOpenIDBundle:ClientMetadata');
201
202
        return $repo->findOneBy(['client' => $client]);
203
    }
204
205
    /**
206
     * @return object|Server
207
     */
208
    private function getOAuth2Server()
209
    {
210
        return $this->get('oauth2.server');
211
    }
212
213
    /**
214
     * @param array $scopes
215
     * @return array
216
     */
217
    private function removeRemoteScope(array $scopes)
218
    {
219
        return array_filter($scopes, function ($scope) {
220
            if (preg_match('/^tag:/', $scope) === 1) {
221
                return false;
222
            }
223
224
            return true;
225
        });
226
    }
227
}
228