Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Authentication;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Routing\RouteMatch;
|
Chris@0
|
6 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * Manager for authentication.
|
Chris@0
|
10 *
|
Chris@0
|
11 * On each request, let all authentication providers try to authenticate the
|
Chris@0
|
12 * user. The providers are iterated according to their priority and the first
|
Chris@0
|
13 * provider detecting credentials for its method wins. No further provider will
|
Chris@0
|
14 * get triggered.
|
Chris@0
|
15 *
|
Chris@0
|
16 * If no provider set an active user then the user is set to anonymous.
|
Chris@0
|
17 */
|
Chris@0
|
18 class AuthenticationManager implements AuthenticationProviderInterface, AuthenticationProviderFilterInterface, AuthenticationProviderChallengeInterface {
|
Chris@0
|
19
|
Chris@0
|
20 /**
|
Chris@0
|
21 * The authentication provider collector.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @var \Drupal\Core\Authentication\AuthenticationCollectorInterface
|
Chris@0
|
24 */
|
Chris@0
|
25 protected $authCollector;
|
Chris@0
|
26
|
Chris@0
|
27 /**
|
Chris@0
|
28 * Creates a new authentication manager instance.
|
Chris@0
|
29 *
|
Chris@0
|
30 * @param \Drupal\Core\Authentication\AuthenticationCollectorInterface $auth_collector
|
Chris@0
|
31 * The authentication provider collector.
|
Chris@0
|
32 */
|
Chris@0
|
33 public function __construct(AuthenticationCollectorInterface $auth_collector) {
|
Chris@0
|
34 $this->authCollector = $auth_collector;
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@0
|
38 * {@inheritdoc}
|
Chris@0
|
39 */
|
Chris@0
|
40 public function applies(Request $request) {
|
Chris@0
|
41 return (bool) $this->getProvider($request);
|
Chris@0
|
42 }
|
Chris@0
|
43
|
Chris@0
|
44 /**
|
Chris@0
|
45 * {@inheritdoc}
|
Chris@0
|
46 */
|
Chris@0
|
47 public function authenticate(Request $request) {
|
Chris@0
|
48 $provider_id = $this->getProvider($request);
|
Chris@0
|
49 $provider = $this->authCollector->getProvider($provider_id);
|
Chris@0
|
50
|
Chris@0
|
51 if ($provider) {
|
Chris@0
|
52 return $provider->authenticate($request);
|
Chris@0
|
53 }
|
Chris@0
|
54
|
Chris@0
|
55 return NULL;
|
Chris@0
|
56 }
|
Chris@0
|
57
|
Chris@0
|
58 /**
|
Chris@0
|
59 * {@inheritdoc}
|
Chris@0
|
60 */
|
Chris@0
|
61 public function appliesToRoutedRequest(Request $request, $authenticated) {
|
Chris@0
|
62 $result = FALSE;
|
Chris@0
|
63
|
Chris@0
|
64 if ($authenticated) {
|
Chris@0
|
65 $result = $this->applyFilter($request, $authenticated, $this->getProvider($request));
|
Chris@0
|
66 }
|
Chris@0
|
67 else {
|
Chris@0
|
68 foreach ($this->authCollector->getSortedProviders() as $provider_id => $provider) {
|
Chris@0
|
69 if ($this->applyFilter($request, $authenticated, $provider_id)) {
|
Chris@0
|
70 $result = TRUE;
|
Chris@0
|
71 break;
|
Chris@0
|
72 }
|
Chris@0
|
73 }
|
Chris@0
|
74 }
|
Chris@0
|
75
|
Chris@0
|
76 return $result;
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 /**
|
Chris@0
|
80 * {@inheritdoc}
|
Chris@0
|
81 */
|
Chris@0
|
82 public function challengeException(Request $request, \Exception $previous) {
|
Chris@0
|
83 $provider_id = $this->getChallenger($request);
|
Chris@0
|
84
|
Chris@0
|
85 if ($provider_id) {
|
Chris@0
|
86 $provider = $this->authCollector->getProvider($provider_id);
|
Chris@0
|
87 return $provider->challengeException($request, $previous);
|
Chris@0
|
88 }
|
Chris@0
|
89 }
|
Chris@0
|
90
|
Chris@0
|
91 /**
|
Chris@0
|
92 * Returns the id of the authentication provider for a request.
|
Chris@0
|
93 *
|
Chris@0
|
94 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
95 * The incoming request.
|
Chris@0
|
96 *
|
Chris@0
|
97 * @return string|null
|
Chris@0
|
98 * The id of the first authentication provider which applies to the request.
|
Chris@0
|
99 * If no application detects appropriate credentials, then NULL is returned.
|
Chris@0
|
100 */
|
Chris@0
|
101 protected function getProvider(Request $request) {
|
Chris@0
|
102 foreach ($this->authCollector->getSortedProviders() as $provider_id => $provider) {
|
Chris@0
|
103 if ($provider->applies($request)) {
|
Chris@0
|
104 return $provider_id;
|
Chris@0
|
105 }
|
Chris@0
|
106 }
|
Chris@0
|
107 }
|
Chris@0
|
108
|
Chris@0
|
109 /**
|
Chris@0
|
110 * Returns the ID of the challenge provider for a request.
|
Chris@0
|
111 *
|
Chris@0
|
112 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
113 * The incoming request.
|
Chris@0
|
114 *
|
Chris@0
|
115 * @return string|null
|
Chris@0
|
116 * The ID of the first authentication provider which applies to the request.
|
Chris@0
|
117 * If no application detects appropriate credentials, then NULL is returned.
|
Chris@0
|
118 */
|
Chris@0
|
119 protected function getChallenger(Request $request) {
|
Chris@0
|
120 foreach ($this->authCollector->getSortedProviders() as $provider_id => $provider) {
|
Chris@0
|
121 if (($provider instanceof AuthenticationProviderChallengeInterface) && !$provider->applies($request) && $this->applyFilter($request, FALSE, $provider_id)) {
|
Chris@0
|
122 return $provider_id;
|
Chris@0
|
123 }
|
Chris@0
|
124 }
|
Chris@0
|
125 }
|
Chris@0
|
126
|
Chris@0
|
127 /**
|
Chris@0
|
128 * Checks whether a provider is allowed on the given request.
|
Chris@0
|
129 *
|
Chris@0
|
130 * If no filter is registered for the given provider id, the default filter
|
Chris@0
|
131 * is applied.
|
Chris@0
|
132 *
|
Chris@0
|
133 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
134 * The incoming request.
|
Chris@0
|
135 * @param bool $authenticated
|
Chris@0
|
136 * Whether or not the request is authenticated.
|
Chris@0
|
137 * @param string $provider_id
|
Chris@0
|
138 * The id of the authentication provider to check access for.
|
Chris@0
|
139 *
|
Chris@0
|
140 * @return bool
|
Chris@0
|
141 * TRUE if provider is allowed, FALSE otherwise.
|
Chris@0
|
142 */
|
Chris@0
|
143 protected function applyFilter(Request $request, $authenticated, $provider_id) {
|
Chris@0
|
144 $provider = $this->authCollector->getProvider($provider_id);
|
Chris@0
|
145
|
Chris@0
|
146 if ($provider && ($provider instanceof AuthenticationProviderFilterInterface)) {
|
Chris@0
|
147 $result = $provider->appliesToRoutedRequest($request, $authenticated);
|
Chris@0
|
148 }
|
Chris@0
|
149 else {
|
Chris@0
|
150 $result = $this->defaultFilter($request, $provider_id);
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 return $result;
|
Chris@0
|
154 }
|
Chris@0
|
155
|
Chris@0
|
156 /**
|
Chris@0
|
157 * Default implementation of the provider filter.
|
Chris@0
|
158 *
|
Chris@0
|
159 * Checks whether a provider is allowed as per the _auth option on a route. If
|
Chris@0
|
160 * the option is not set or if the request did not match any route, only
|
Chris@0
|
161 * providers from the global provider set are allowed.
|
Chris@0
|
162 *
|
Chris@0
|
163 * If no filter is registered for the given provider id, the default filter
|
Chris@0
|
164 * is applied.
|
Chris@0
|
165 *
|
Chris@0
|
166 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
167 * The incoming request.
|
Chris@0
|
168 * @param string $provider_id
|
Chris@0
|
169 * The id of the authentication provider to check access for.
|
Chris@0
|
170 *
|
Chris@0
|
171 * @return bool
|
Chris@0
|
172 * TRUE if provider is allowed, FALSE otherwise.
|
Chris@0
|
173 */
|
Chris@0
|
174 protected function defaultFilter(Request $request, $provider_id) {
|
Chris@0
|
175 $route = RouteMatch::createFromRequest($request)->getRouteObject();
|
Chris@0
|
176 $has_auth_option = isset($route) && $route->hasOption('_auth');
|
Chris@0
|
177
|
Chris@0
|
178 if ($has_auth_option) {
|
Chris@0
|
179 return in_array($provider_id, $route->getOption('_auth'));
|
Chris@0
|
180 }
|
Chris@0
|
181 else {
|
Chris@0
|
182 return $this->authCollector->isGlobal($provider_id);
|
Chris@0
|
183 }
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 }
|