You are here

public function CasGatewayAuthSubscriber::onRequest in CAS 2.x

Respond to request events.

This is the server-side implementaton of CAS gateway authentication.

This works by having Drupal return a redirect to the CAS server for the gateway auth check. Caching is disabled on all paths this would be active on. See the DenyCas response policy file.

Parameters

\Symfony\Component\HttpKernel\Event\GetResponseEvent $event: The event.

File

src/Subscriber/CasGatewayAuthSubscriber.php, line 157

Class

CasGatewayAuthSubscriber
Event subscriber for implementing CAS gateway authentication.

Namespace

Drupal\cas\Subscriber

Code

public function onRequest(GetResponseEvent $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;
  }
  if (!$this->gatewayEnabled || $this->gatewayMethod !== CasHelper::GATEWAY_SERVER_SIDE) {
    return;
  }

  // Only care about anonymous users.
  if ($this->currentUser
    ->isAuthenticated()) {
    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;
  }

  // Don't do anything if this is a request from cron, drush, crawler, etc.
  if ($this
    ->isCrawlerRequest($event
    ->getRequest())) {
    return;
  }

  // User can indicate specific paths to enable (or disable) gateway mode.
  $condition = $this->conditionManager
    ->createInstance('request_path');
  $condition
    ->setConfiguration($this->gatewayPaths);
  if (!$this->conditionManager
    ->execute($condition)) {
    return;
  }

  // Don't perform the auth check if we just returned from one.
  // This prevents an infinite redirect loop.
  $session = $event
    ->getRequest()
    ->getSession();
  if ($session && $session
    ->has('cas_temp_disable_gateway_auth')) {
    $session
      ->remove('cas_temp_disable_gateway_auth');
    $this->casHelper
      ->log(LogLevel::DEBUG, "CAS gateway auth temporary disable flag set, skipping.");
    return;
  }

  // Do nothing if we're configured to only check once per period of time
  // and that length of time hasn't passed yet. The cookie is time-based
  // and browsers will stop sending it after it has expired. That's when we
  // know it's OK to check again.
  if ($this->gatewayRecheckTime > 0 && $event
    ->getRequest()->cookies
    ->has('cas_gateway_checked_ss')) {
    $this->casHelper
      ->log(LogLevel::DEBUG, 'CAS gateway auth has already been performed recently, skipping.');
    return;
  }

  // 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.
  $currentPath = str_replace($event
    ->getRequest()
    ->getSchemeAndHttpHost(), '', $event
    ->getRequest()
    ->getUri());
  $redirectData = new CasRedirectData([
    'destination' => $currentPath,
    'from_gateway' => TRUE,
  ], [
    'gateway' => 'true',
  ]);
  $this->casHelper
    ->log(LogLevel::DEBUG, 'Initializing gateway auth from CasSubscriber.');
  $response = $this->casRedirector
    ->buildRedirectResponse($redirectData);
  if ($response) {

    // If configured to only perform gateway auth check once per period of
    // time, then set a cookie for that period of time to prevent future
    // auth checks.
    if ($this->gatewayRecheckTime > 0) {
      $expireTime = time() + 60 * $this->gatewayRecheckTime;
      $cookie = new Cookie('cas_gateway_checked_ss', 1, $expireTime);
      $response->headers
        ->setCookie($cookie);
    }
    $event
      ->setResponse($response);

    // If there's a 'destination' parameter set on the current request,
    // remove it, otherwise Drupal's RedirectResponseSubscriber will send
    // users to that location instead of the CAS server.
    $event
      ->getRequest()->query
      ->remove('destination');

    // Set a temp session var that will block our subscriber from doing
    // doing anything on the next request. Without this, we'll create a
    // redirect loop as the gateway subscriber will just immediately redirect
    // the user back to the CAS server again.
    if ($this->gatewayMethod === CasHelper::GATEWAY_SERVER_SIDE) {
      $event
        ->getRequest()
        ->getSession()
        ->set('cas_temp_disable_gateway_auth', TRUE);
    }
  }
}