function SessionHttpsTestCase::testHttpsSession

File

modules/simpletest/tests/session.test, line 566

Class

SessionHttpsTestCase
Ensure that when running under HTTPS two session cookies are generated.

Code

protected function testHttpsSession() {
  global $is_https;
  if ($is_https) {
    $secure_session_name = session_name();
    $insecure_session_name = substr(session_name(), 1);
  }
  else {
    $secure_session_name = 'S' . session_name();
    $insecure_session_name = session_name();
  }
  $user = $this->drupalCreateUser(array(
    'access administration pages',
  ));
  // Test HTTPS session handling by altering the form action to submit the
  // login form through https.php, which creates a mock HTTPS request.
  $this->drupalGet('user');
  $form = $this->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this->httpsUrl('user');
  $edit = array(
    'name' => $user->name,
    'pass' => $user->pass_raw,
  );
  $this->drupalPost(NULL, $edit, t('Log in'));
  // Test a second concurrent session.
  $this->curlClose();
  $this->drupalGet('user');
  $form = $this->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this->httpsUrl('user');
  $this->drupalPost(NULL, $edit, t('Log in'));
  // Check secure cookie on secure page.
  $this->assertTrue($this->cookies[$secure_session_name]['secure'], 'The secure cookie has the secure attribute');
  // Check insecure cookie is not set.
  $this->assertFalse(isset($this->cookies[$insecure_session_name]));
  $ssid = $this->cookies[$secure_session_name]['value'];
  $this->assertSessionIds($ssid, $ssid, 'Session has a non-empty SID and a correct secure SID.');
  $cookie = $secure_session_name . '=' . $ssid;
  // Verify that user is logged in on secure URL.
  $this->curlClose();
  $this->drupalGet($this->httpsUrl('admin/config'), array(), array(
    'Cookie: ' . $cookie,
  ));
  $this->assertText(t('Configuration'));
  $this->assertResponse(200);
  // Verify that user is not logged in on non-secure URL.
  $this->curlClose();
  $this->drupalGet($this->httpUrl('admin/config'), array(), array(
    'Cookie: ' . $cookie,
  ));
  $this->assertNoText(t('Configuration'));
  $this->assertResponse(403);
  // Verify that empty SID cannot be used on the non-secure site.
  $this->curlClose();
  $cookie = $insecure_session_name . '=';
  $this->drupalGet($this->httpUrl('admin/config'), array(), array(
    'Cookie: ' . $cookie,
  ));
  $this->assertResponse(403);
  // Test HTTP session handling by altering the form action to submit the
  // login form through http.php, which creates a mock HTTP request on HTTPS
  // test environments.
  $this->curlClose();
  $this->drupalGet('user');
  $form = $this->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this->httpUrl('user');
  $edit = array(
    'name' => $user->name,
    'pass' => $user->pass_raw,
  );
  $this->drupalPost(NULL, $edit, t('Log in'));
  $this->drupalGet($this->httpUrl('admin/config'));
  $this->assertResponse(200);
  $sid = $this->cookies[$insecure_session_name]['value'];
  $this->assertSessionIds($sid, '', 'Session has the correct SID and an empty secure SID.');
  // Verify that empty secure SID cannot be used on the secure site.
  $this->curlClose();
  $cookie = $secure_session_name . '=';
  $this->drupalGet($this->httpsUrl('admin/config'), array(), array(
    'Cookie: ' . $cookie,
  ));
  $this->assertResponse(403);
  // Clear browser cookie jar.
  $this->cookies = array();
  if ($is_https) {
    // The functionality does not make sense when running on HTTPS.
    return;
  }
  // Enable secure pages.
  variable_set('https', TRUE);
  $this->curlClose();
  // Start an anonymous session on the insecure site.
  $session_data = $this->randomName();
  $this->drupalGet('session-test/set/' . $session_data);
  // Check secure cookie on insecure page.
  $this->assertFalse(isset($this->cookies[$secure_session_name]), 'The secure cookie is not sent on insecure pages.');
  // Check insecure cookie on insecure page.
  $this->assertFalse($this->cookies[$insecure_session_name]['secure'], 'The insecure cookie does not have the secure attribute');
  // Store the anonymous cookie so we can validate that its session is killed
  // after login.
  $anonymous_cookie = $insecure_session_name . '=' . $this->cookies[$insecure_session_name]['value'];
  // Check that password request form action is not secure.
  $this->drupalGet('user/password');
  $form = $this->xpath('//form[@id="user-pass"]');
  $this->assertNotEqual(substr($form[0]['action'], 0, 6), 'https:', 'Password request form action is not secure');
  $form[0]['action'] = $this->httpsUrl('user');
  // Check that user login form action is secure.
  $this->drupalGet('user');
  $form = $this->xpath('//form[@id="user-login"]');
  $this->assertEqual(substr($form[0]['action'], 0, 6), 'https:', 'Login form action is secure');
  $form[0]['action'] = $this->httpsUrl('user');
  $edit = array(
    'name' => $user->name,
    'pass' => $user->pass_raw,
  );
  $this->drupalPost(NULL, $edit, t('Log in'));
  // Check secure cookie on secure page.
  $this->assertTrue($this->cookies[$secure_session_name]['secure'], 'The secure cookie has the secure attribute');
  // Check insecure cookie on secure page.
  $this->assertFalse($this->cookies[$insecure_session_name]['secure'], 'The insecure cookie does not have the secure attribute');
  $sid = $this->cookies[$insecure_session_name]['value'];
  $ssid = $this->cookies[$secure_session_name]['value'];
  $this->assertSessionIds($sid, $ssid, 'Session has both secure and insecure SIDs');
  $cookies = array(
    $insecure_session_name . '=' . $sid,
    $secure_session_name . '=' . $ssid,
  );
  // Test that session data saved before login is still available on the
  // authenticated session.
  $this->drupalGet('session-test/get');
  $this->assertText($session_data, 'Session correctly returned the stored data set by the anonymous session.');
  foreach ($cookies as $cookie_key => $cookie) {
    foreach (array(
      'admin/config',
      $this->httpsUrl('admin/config'),
    ) as $url_key => $url) {
      $this->curlClose();
      $this->drupalGet($url, array(), array(
        'Cookie: ' . $cookie,
      ));
      if ($cookie_key == $url_key) {
        $this->assertText(t('Configuration'));
        $this->assertResponse(200);
      }
      else {
        $this->assertNoText(t('Configuration'));
        $this->assertResponse(403);
      }
    }
  }
  // Test that session data saved before login is not available using the
  // pre-login anonymous cookie.
  $this->cookies = array();
  $this->drupalGet('session-test/get', array(
    'Cookie: ' . $anonymous_cookie,
  ));
  $this->assertNoText($session_data, 'Initial anonymous session is inactive after login.');
  // Clear browser cookie jar.
  $this->cookies = array();
  // Start an anonymous session on the secure site.
  $this->drupalGet($this->httpsUrl('session-test/set/1'));
  // Mock a login to the secure site using the secure session cookie.
  $this->drupalGet('user');
  $form = $this->xpath('//form[@id="user-login"]');
  $form[0]['action'] = $this->httpsUrl('user');
  $this->drupalPost(NULL, $edit, t('Log in'));
  // Test that the user is also authenticated on the insecure site.
  $this->drupalGet("user/{$user->uid}/edit");
  $this->assertResponse(200);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.