1+ <?php
2+
3+ namespace App \Application \EventSubscriber ;
4+
5+ use App \Presentation \Api \Rest \Controller \TokenAuthenticatedController ;
6+ use League \OAuth2 \Server \Exception \OAuthServerException ;
7+ use League \OAuth2 \Server \ResourceServer ;
8+ use Psr \Http \Message \ServerRequestInterface ;
9+ use Symfony \Bridge \PsrHttpMessage \Factory \DiactorosFactory ;
10+ use Symfony \Component \EventDispatcher \EventSubscriberInterface ;
11+ use Symfony \Component \HttpFoundation \JsonResponse ;
12+ use Symfony \Component \HttpFoundation \Request ;
13+ use Symfony \Component \HttpFoundation \Response ;
14+ use Symfony \Component \HttpKernel \Event \FilterControllerEvent ;
15+ use Symfony \Component \HttpKernel \Event \GetResponseForExceptionEvent ;
16+ use Symfony \Component \HttpKernel \KernelEvents ;
17+
18+ final class TokenSubscriber implements EventSubscriberInterface
19+ {
20+ /**
21+ * @var ResourceServer
22+ */
23+ private $ resourceServer ;
24+
25+ /**
26+ * TokenSubscriber constructor.
27+ * @param ResourceServer $resourceServer
28+ */
29+ public function __construct (ResourceServer $ resourceServer )
30+ {
31+ $ this ->resourceServer = $ resourceServer ;
32+ }
33+
34+ /**
35+ * @return array
36+ */
37+ public static function getSubscribedEvents (): array
38+ {
39+ return [
40+ KernelEvents::CONTROLLER => 'onKernelController ' ,
41+ KernelEvents::EXCEPTION => 'onKernelException '
42+ ];
43+ }
44+
45+ /**
46+ * @param FilterControllerEvent $event
47+ * @throws OAuthServerException
48+ */
49+ public function onKernelController (FilterControllerEvent $ event ): void
50+ {
51+ $ controller = $ event ->getController ();
52+
53+ /*
54+ * $controller passed can be either a class or a Closure.
55+ * This is not usual in Symfony but it may happen.
56+ * If it is a class, it comes in array format
57+ */
58+ if (!\is_array ($ controller )) {
59+ return ;
60+ }
61+
62+ if ($ controller [0 ] instanceof TokenAuthenticatedController) {
63+ $ request = $ event ->getRequest ();
64+ $ psrRequest = (new DiactorosFactory )->createRequest ($ request );
65+ try {
66+ $ psrRequest = $ this ->resourceServer ->validateAuthenticatedRequest ($ psrRequest );
67+ } catch (OAuthServerException $ exception ) {
68+ throw $ exception ;
69+ } catch (\Exception $ exception ) {
70+ throw new OAuthServerException ($ exception ->getMessage (), 0 , 'unknown_error ' , Response::HTTP_INTERNAL_SERVER_ERROR );
71+ }
72+
73+ $ this ->enrichSymfonyRequestWithAuthData ($ request , $ psrRequest );
74+ }
75+ }
76+
77+ /**
78+ * @param Request $request
79+ * @param ServerRequestInterface $psrRequest
80+ */
81+ private function enrichSymfonyRequestWithAuthData (Request $ request , ServerRequestInterface $ psrRequest ): void
82+ {
83+ $ request = $ request ->request ;
84+ $ requestArray = $ request ->all ();
85+ $ requestArray ['oauth_user_id ' ] = $ psrRequest ->getAttribute ('oauth_user_id ' );
86+ $ requestArray ['oauth_access_token_id ' ] = $ psrRequest ->getAttribute ('oauth_access_token_id ' );
87+ $ requestArray ['oauth_client_id ' ] = $ psrRequest ->getAttribute ('oauth_client_id ' );
88+ $ request ->replace ($ requestArray );
89+ }
90+
91+ /**
92+ * @param GetResponseForExceptionEvent $event
93+ */
94+ public function onKernelException (GetResponseForExceptionEvent $ event ): void
95+ {
96+ $ exception = $ event ->getException ();
97+
98+ if (!($ exception instanceof OAuthServerException)) {
99+ return ;
100+ }
101+
102+ $ response = new JsonResponse (['error ' => $ exception ->getMessage ()], $ exception ->getHttpStatusCode ());
103+ $ event ->setResponse ($ response );
104+ }
105+ }
0 commit comments