public function CasGatewayAuthSubscriber::onResponse in CAS 2.x
Handle response event.
This is the client-side implementaton (JS) of CAS gateway authentication.
This works by attaching a JS library to the HTML response that will redirect the user agent to the CAS server for the gateway check.
Unlike the server-side implementation, this one works with page caching so we need to set appropriate cache metadata.
Parameters
\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event: The event.
File
- src/
Subscriber/ CasGatewayAuthSubscriber.php, line 265
Class
- CasGatewayAuthSubscriber
- Event subscriber for implementing CAS gateway authentication.
Namespace
Drupal\cas\SubscriberCode
public function onResponse(FilterResponseEvent $event) {
if (!$event
->isMasterRequest()) {
return;
}
// Only implement gateway feature for GET requests, to prevent users from
// being redirected to CAS server for things like form submissions.
if (!$event
->getRequest()
->isMethod('GET')) {
return;
}
// Build up some cache metadata we'll need to attach to the response.
$cacheMetadata = new CacheableMetadata();
$response = $event
->getResponse();
// Make sure we're configured for client-side gateway auth.
$cacheMetadata
->addCacheTags([
'config:cas.settings',
]);
if (!$this->gatewayEnabled || $this->gatewayMethod !== CasHelper::GATEWAY_CLIENT_SIDE) {
$this
->addCacheMetadataToResponse($response, $cacheMetadata);
return;
}
// Only care about anonymous users.
$cacheMetadata
->addCacheContexts([
'user.roles:authenticated',
]);
if ($this->currentUser
->isAuthenticated()) {
$this
->addCacheMetadataToResponse($response, $cacheMetadata);
return;
}
$cacheMetadata
->addCacheContexts([
'request_format',
]);
if (!$response instanceof HtmlResponse) {
$this
->addCacheMetadataToResponse($response, $cacheMetadata);
return;
}
// Some routes we don't want to run on.
$current_route = $this->routeMatcher
->getRouteName();
if (in_array($current_route, CasHelper::IGNOREABLE_AUTO_LOGIN_ROUTES)) {
return;
}
// Check that the path matches what's been configured.
// The cache context on the request path condition plugin is url.path
// which is an "expensive" context, as it makes dynamic page cache
// quite useless for serving 404 pages. Avoid it if we know the only
// path we care about is the front page, which is a common config for
// gateway.
if (trim($this->gatewayPaths['pages']) === '<front>') {
$cacheMetadata
->addCacheContexts([
'url.path.is_front',
]);
}
else {
$cacheMetadata
->addCacheContexts([
'url.path',
]);
}
$condition = $this->conditionManager
->createInstance('request_path');
$gatewayPaths = $this->gatewayPaths;
$condition
->setConfiguration($gatewayPaths);
if (!$this->conditionManager
->execute($condition)) {
$this
->addCacheMetadataToResponse($response, $cacheMetadata);
return;
}
// We're good to activate gateway redirect. Add all the cache metadata we've
// built up to the existing page response and add our front-end library
// that performs the redirect.
$this
->addCacheMetadataToResponse($response, $cacheMetadata);
// Start constructing the URL redirect to CAS for gateway auth.
// Add the current path to the service URL as the 'destination' param,
// so that when the ServiceController eventually processess the login,
// it knows to return the user back here.
$request = $event
->getRequest();
$currentPath = str_replace($request
->getSchemeAndHttpHost(), '', $request
->getUri());
$redirectData = new CasRedirectData([
'destination' => $currentPath,
'from_gateway' => TRUE,
], [
'gateway' => 'true',
]);
$redirectResponse = $this->casRedirector
->buildRedirectResponse($redirectData);
if ($redirectResponse) {
// Add our JS library used for redirecting and provide the redirect URL
// and check frequency.
$attachments = [];
$attachments['library'][] = 'cas/client_side_gateway_redirect';
$attachments['drupalSettings']['cas'] = [
'gatewayRedirectUrl' => $redirectResponse
->getTargetUrl(),
'recheckTime' => $this->gatewayRecheckTime,
// We pass the list of known crawlers to the client so it knows not
// to activate the redirect if the request comes from these. If we did
// this check server-side, it wouldn't be compatible with caching
// without varying every cache entry by user agent which is not
// practical.
'knownCrawlers' => implode('|', $this
->getKnownCrawlersList()),
];
$response
->addAttachments($attachments);
}
}