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.