protected function SessionHttpsTestCase::testHttpsSession

7.x session.test protected SessionHttpsTestCase::testHttpsSession()

File

drupal-7.x/modules/simpletest/tests/session.test, line 307
Provides SimpleTests for core session handling functionality.

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);
}