Failed Conditions
Push — issue#666 ( 521a08...be48ce )
by Guilherme
09:34
created

AuthorizeController::getSectorIdentifierUriChecker()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
class AuthorizeController extends BaseController
31
{
32
33
    /**
34
     * @Route("/openid/connect/authorize", name="_authorize_handle")
35
     * @Method({"POST"})
36
     */
37
    public function handleAuthorizeAction()
38
    {
39
        $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

39
        $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...
40
        $implodedScope = implode(' ', $request->request->get('scope'));
41
        $request->request->set('scope', $implodedScope);
42
43
        $isAuthorized = $request->request->has('accepted')
44
            || !$request->request->has('rejected');
45
46
        $response = $this->handleAuthorize($this->getOAuth2Server(), $isAuthorized);
47
48
        $event = new OAuthEvent(
49
            $this->getUser(),
50
            $this->getClient($request), $isAuthorized
51
        );
52
53
        /** @var EventDispatcherInterface $dispatcher */
54
        $dispatcher = $this->get('event_dispatcher');
55
        $dispatcher->dispatch(OAuthEvent::POST_AUTHORIZATION_PROCESS, $event);
56
57
        return $response;
58
    }
59
60
    /**
61
     * Render the Authorization fragment
62
     *
63
     * @Template()
64
     *
65
     * @deprecated
66
     */
67
    public function authorizeAction()
68
    {
69
        throw new \RuntimeException('This class should not be used!');
70
    }
71
72
    /**
73
     * @Route("/openid/connect/authorize", name="_authorize_validate")
74
     * @Method({"GET"})
75
     * @Template("LoginCidadaoOpenIDBundle:Authorize:authorize.html.twig")
76
     */
77
    public function validateAuthorizeAction()
78
    {
79
        $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

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