Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\EventSubscriber;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Authentication\AuthenticationProviderFilterInterface;
|
Chris@0
|
6 use Drupal\Core\Authentication\AuthenticationProviderChallengeInterface;
|
Chris@0
|
7 use Drupal\Core\Authentication\AuthenticationProviderInterface;
|
Chris@0
|
8 use Drupal\Core\Session\AccountProxyInterface;
|
Chris@0
|
9 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
Chris@0
|
10 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
Chris@0
|
11 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
Chris@0
|
12 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
Chris@0
|
13 use Symfony\Component\HttpKernel\HttpKernelInterface;
|
Chris@0
|
14 use Symfony\Component\HttpKernel\KernelEvents;
|
Chris@0
|
15
|
Chris@0
|
16 /**
|
Chris@0
|
17 * Authentication subscriber.
|
Chris@0
|
18 *
|
Chris@0
|
19 * Trigger authentication during the request.
|
Chris@0
|
20 */
|
Chris@0
|
21 class AuthenticationSubscriber implements EventSubscriberInterface {
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * Authentication provider.
|
Chris@0
|
25 *
|
Chris@0
|
26 * @var \Drupal\Core\Authentication\AuthenticationProviderInterface
|
Chris@0
|
27 */
|
Chris@0
|
28 protected $authenticationProvider;
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * Authentication provider filter.
|
Chris@0
|
32 *
|
Chris@0
|
33 * @var \Drupal\Core\Authentication\AuthenticationProviderFilterInterface|null
|
Chris@0
|
34 */
|
Chris@0
|
35 protected $filter;
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@0
|
38 * Authentication challenge provider.
|
Chris@0
|
39 *
|
Chris@0
|
40 * @var \Drupal\Core\Authentication\AuthenticationProviderChallengeInterface|null
|
Chris@0
|
41 */
|
Chris@0
|
42 protected $challengeProvider;
|
Chris@0
|
43
|
Chris@0
|
44 /**
|
Chris@0
|
45 * Account proxy.
|
Chris@0
|
46 *
|
Chris@0
|
47 * @var \Drupal\Core\Session\AccountProxyInterface
|
Chris@0
|
48 */
|
Chris@0
|
49 protected $accountProxy;
|
Chris@0
|
50
|
Chris@0
|
51 /**
|
Chris@0
|
52 * Constructs an authentication subscriber.
|
Chris@0
|
53 *
|
Chris@0
|
54 * @param \Drupal\Core\Authentication\AuthenticationProviderInterface $authentication_provider
|
Chris@0
|
55 * An authentication provider.
|
Chris@0
|
56 * @param \Drupal\Core\Session\AccountProxyInterface $account_proxy
|
Chris@0
|
57 * Account proxy.
|
Chris@0
|
58 */
|
Chris@0
|
59 public function __construct(AuthenticationProviderInterface $authentication_provider, AccountProxyInterface $account_proxy) {
|
Chris@0
|
60 $this->authenticationProvider = $authentication_provider;
|
Chris@0
|
61 $this->filter = ($authentication_provider instanceof AuthenticationProviderFilterInterface) ? $authentication_provider : NULL;
|
Chris@0
|
62 $this->challengeProvider = ($authentication_provider instanceof AuthenticationProviderChallengeInterface) ? $authentication_provider : NULL;
|
Chris@0
|
63 $this->accountProxy = $account_proxy;
|
Chris@0
|
64 }
|
Chris@0
|
65
|
Chris@0
|
66 /**
|
Chris@0
|
67 * Authenticates user on request.
|
Chris@0
|
68 *
|
Chris@0
|
69 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
Chris@0
|
70 * The request event.
|
Chris@0
|
71 *
|
Chris@0
|
72 * @see \Drupal\Core\Authentication\AuthenticationProviderInterface::authenticate()
|
Chris@0
|
73 */
|
Chris@0
|
74 public function onKernelRequestAuthenticate(GetResponseEvent $event) {
|
Chris@0
|
75 if ($event->getRequestType() === HttpKernelInterface::MASTER_REQUEST) {
|
Chris@0
|
76 $request = $event->getRequest();
|
Chris@0
|
77 if ($this->authenticationProvider->applies($request)) {
|
Chris@0
|
78 $account = $this->authenticationProvider->authenticate($request);
|
Chris@0
|
79 if ($account) {
|
Chris@0
|
80 $this->accountProxy->setAccount($account);
|
Chris@0
|
81 return;
|
Chris@0
|
82 }
|
Chris@0
|
83 }
|
Chris@0
|
84 // No account has been set explicitly, initialize the timezone here.
|
Chris@0
|
85 date_default_timezone_set(drupal_get_user_timezone());
|
Chris@0
|
86 }
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 /**
|
Chris@0
|
90 * Denies access if authentication provider is not allowed on this route.
|
Chris@0
|
91 *
|
Chris@0
|
92 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
Chris@0
|
93 * The request event.
|
Chris@0
|
94 */
|
Chris@0
|
95 public function onKernelRequestFilterProvider(GetResponseEvent $event) {
|
Chris@0
|
96 if (isset($this->filter) && $event->getRequestType() === HttpKernelInterface::MASTER_REQUEST) {
|
Chris@0
|
97 $request = $event->getRequest();
|
Chris@0
|
98 if ($this->authenticationProvider->applies($request) && !$this->filter->appliesToRoutedRequest($request, TRUE)) {
|
Chris@0
|
99 throw new AccessDeniedHttpException('The used authentication method is not allowed on this route.');
|
Chris@0
|
100 }
|
Chris@0
|
101 }
|
Chris@0
|
102 }
|
Chris@0
|
103
|
Chris@0
|
104 /**
|
Chris@0
|
105 * Respond with a challenge on access denied exceptions if appropriate.
|
Chris@0
|
106 *
|
Chris@0
|
107 * On a 403 (access denied), if there are no credentials on the request, some
|
Chris@0
|
108 * authentication methods (e.g. basic auth) require that a challenge is sent
|
Chris@0
|
109 * to the client.
|
Chris@0
|
110 *
|
Chris@0
|
111 * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
|
Chris@0
|
112 * The exception event.
|
Chris@0
|
113 */
|
Chris@0
|
114 public function onExceptionSendChallenge(GetResponseForExceptionEvent $event) {
|
Chris@0
|
115 if (isset($this->challengeProvider) && $event->getRequestType() === HttpKernelInterface::MASTER_REQUEST) {
|
Chris@0
|
116 $request = $event->getRequest();
|
Chris@0
|
117 $exception = $event->getException();
|
Chris@0
|
118 if ($exception instanceof AccessDeniedHttpException && !$this->authenticationProvider->applies($request) && (!isset($this->filter) || $this->filter->appliesToRoutedRequest($request, FALSE))) {
|
Chris@0
|
119 $challenge_exception = $this->challengeProvider->challengeException($request, $exception);
|
Chris@0
|
120 if ($challenge_exception) {
|
Chris@0
|
121 $event->setException($challenge_exception);
|
Chris@0
|
122 }
|
Chris@0
|
123 }
|
Chris@0
|
124 }
|
Chris@0
|
125 }
|
Chris@0
|
126
|
Chris@0
|
127 /**
|
Chris@0
|
128 * {@inheritdoc}
|
Chris@0
|
129 */
|
Chris@0
|
130 public static function getSubscribedEvents() {
|
Chris@0
|
131 // The priority for authentication must be higher than the highest event
|
Chris@0
|
132 // subscriber accessing the current user. Especially it must be higher than
|
Chris@0
|
133 // LanguageRequestSubscriber as LanguageManager accesses the current user if
|
Chris@0
|
134 // the language module is enabled.
|
Chris@0
|
135 $events[KernelEvents::REQUEST][] = ['onKernelRequestAuthenticate', 300];
|
Chris@0
|
136
|
Chris@0
|
137 // Access check must be performed after routing.
|
Chris@0
|
138 $events[KernelEvents::REQUEST][] = ['onKernelRequestFilterProvider', 31];
|
Chris@0
|
139 $events[KernelEvents::EXCEPTION][] = ['onExceptionSendChallenge', 75];
|
Chris@0
|
140 return $events;
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@0
|
143 }
|