annotate core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php @ 19:fa3358dc1485 tip

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