1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of the Explicit Architecture POC, |
7
|
|
|
* which is created on top of the Symfony Demo application. |
8
|
|
|
* |
9
|
|
|
* (c) Herberto Graça <[email protected]> |
10
|
|
|
* |
11
|
|
|
* For the full copyright and license information, please view the LICENSE |
12
|
|
|
* file that was distributed with this source code. |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Acme\App\Infrastructure\Auth\Authentication\Oauth; |
16
|
|
|
|
17
|
|
|
use Acme\App\Core\Port\Auth\Authentication\Oauth\OauthProtectedControllerInterface; |
18
|
|
|
use Exception; |
19
|
|
|
use League\OAuth2\Server\Exception\OAuthServerException; |
20
|
|
|
use League\OAuth2\Server\ResourceServer; |
21
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
22
|
|
|
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; |
23
|
|
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
24
|
|
|
use Symfony\Component\HttpFoundation\JsonResponse; |
25
|
|
|
use Symfony\Component\HttpFoundation\Request; |
26
|
|
|
use Symfony\Component\HttpFoundation\Response; |
27
|
|
|
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; |
28
|
|
|
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; |
29
|
|
|
use Symfony\Component\HttpKernel\KernelEvents; |
30
|
|
|
use function is_array; |
31
|
|
|
|
32
|
|
|
final class OauthProtectedControllerSubscriber implements EventSubscriberInterface |
33
|
|
|
{ |
34
|
|
|
private const DEFAULT_PRIORITY = 20; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var ResourceServer |
38
|
|
|
*/ |
39
|
|
|
private $resourceServer; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var HttpMessageFactoryInterface |
43
|
|
|
*/ |
44
|
|
|
private $psrHttpMessageFactory; |
45
|
|
|
|
46
|
|
|
public function __construct(ResourceServer $resourceServer, HttpMessageFactoryInterface $psrHttpMessageFactory) |
47
|
|
|
{ |
48
|
|
|
$this->resourceServer = $resourceServer; |
49
|
|
|
$this->psrHttpMessageFactory = $psrHttpMessageFactory; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Return the subscribed events, their methods and possibly their priorities |
54
|
|
|
* (the higher the priority the earlier the method is called). |
55
|
|
|
* |
56
|
|
|
* @see http://symfony.com/doc/current/event_dispatcher.html#creating-an-event-subscriber |
57
|
|
|
*/ |
58
|
|
|
public static function getSubscribedEvents(): array |
59
|
|
|
{ |
60
|
|
|
return [ |
61
|
|
|
KernelEvents::CONTROLLER => ['onKernelController', self::DEFAULT_PRIORITY], |
62
|
|
|
KernelEvents::EXCEPTION => ['onKernelException', self::DEFAULT_PRIORITY], |
63
|
|
|
]; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @throws OAuthServerException |
68
|
|
|
*/ |
69
|
|
|
public function onKernelController(FilterControllerEvent $event): void |
70
|
|
|
{ |
71
|
|
|
$controller = $event->getController(); |
72
|
|
|
/* |
73
|
|
|
* $controller passed can be either a class or a Closure. |
74
|
|
|
* This is not usual in Symfony but it may happen. |
75
|
|
|
* If it is a class, it comes in array format |
76
|
|
|
*/ |
77
|
|
|
if (!is_array($controller)) { |
78
|
|
|
return; |
79
|
|
|
} |
80
|
|
|
if ($controller[0] instanceof OauthProtectedControllerInterface) { |
81
|
|
|
$request = $event->getRequest(); |
82
|
|
|
$psrRequest = $this->psrHttpMessageFactory->createRequest($request); |
83
|
|
|
try { |
84
|
|
|
$psrRequest = $this->resourceServer->validateAuthenticatedRequest($psrRequest); |
85
|
|
|
} catch (OAuthServerException $exception) { |
86
|
|
|
throw $exception; |
87
|
|
|
} catch (Exception $exception) { |
88
|
|
|
throw new OAuthServerException( |
89
|
|
|
$exception->getMessage(), |
90
|
|
|
0, |
91
|
|
|
'unknown_error', |
92
|
|
|
Response::HTTP_INTERNAL_SERVER_ERROR |
93
|
|
|
); |
94
|
|
|
} |
95
|
|
|
$this->enrichSymfonyRequestWithAuthData($request, $psrRequest); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
private function enrichSymfonyRequestWithAuthData(Request $request, ServerRequestInterface $psrRequest): void |
100
|
|
|
{ |
101
|
|
|
$request = $request->request; |
102
|
|
|
$requestArray = $request->all(); |
103
|
|
|
$requestArray['oauth_user_id'] = $psrRequest->getAttribute('oauth_user_id'); |
104
|
|
|
$requestArray['oauth_access_token_id'] = $psrRequest->getAttribute('oauth_access_token_id'); |
105
|
|
|
$requestArray['oauth_client_id'] = $psrRequest->getAttribute('oauth_client_id'); |
106
|
|
|
$request->replace($requestArray); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
public function onKernelException(GetResponseForExceptionEvent $event): void |
110
|
|
|
{ |
111
|
|
|
$exception = $event->getException(); |
|
|
|
|
112
|
|
|
if (!$exception instanceof OAuthServerException) { |
113
|
|
|
return; |
114
|
|
|
} |
115
|
|
|
$response = new JsonResponse(['error' => $exception->getMessage()], $exception->getHttpStatusCode()); |
116
|
|
|
$event->setResponse($response); |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.