diff --git a/core/modules/system/src/Tests/Session/SessionHttpsTest.php b/core/modules/system/tests/src/Functional/Session/SessionHttpsTest.php
similarity index 86%
rename from core/modules/system/src/Tests/Session/SessionHttpsTest.php
rename to core/modules/system/tests/src/Functional/Session/SessionHttpsTest.php
index 134ea0961a..a89ce458d5 100644
--- a/core/modules/system/src/Tests/Session/SessionHttpsTest.php
+++ b/core/modules/system/tests/src/Functional/Session/SessionHttpsTest.php
@@ -1,8 +1,9 @@
 <?php
 
-namespace Drupal\system\Tests\Session;
+namespace Drupal\Tests\system\Functional\Session;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
+use GuzzleHttp\Cookie\CookieJar;
 use Symfony\Component\HttpFoundation\Request;
 use Drupal\Component\Utility\Crypt;
 use Drupal\Core\Session\AccountInterface;
@@ -12,7 +13,14 @@
  *
  * @group Session
  */
-class SessionHttpsTest extends WebTestBase {
+class SessionHttpsTest extends BrowserTestBase {
+
+  /**
+   * The cookies of the page currently loaded in the internal browser.
+   *
+   * @var array
+   */
+  protected $cookies = [];
 
   /**
    * The name of the session cookie when using HTTP.
@@ -21,6 +29,11 @@ class SessionHttpsTest extends WebTestBase {
    */
   protected $insecureSessionName;
 
+  /**
+   * The maximum number of redirects to follow when handling responses.
+   */
+  protected $maximumRedirects = 5;
+
   /**
    * The name of the session cookie when using HTTPS.
    *
@@ -143,12 +156,29 @@ protected function loginHttp(AccountInterface $account) {
    */
   protected function loginHttps(AccountInterface $account) {
     $this->drupalGet('user/login');
+    $html = $this->getSession()->getPage()->getHtml();
+
+    $client = $this->getHttpClient();
+    $form_tokens_found = preg_match('/\sname="form_build_id" value="([^"]+)"/', $html, $build_id_match);
+    $this->assertTrue($form_tokens_found, 'Form tokens found in output.');
+
+    $cookie_jar = new CookieJar();
+    $post = [
+      'form_id' => 'user_login_form',
+      'form_build_id' => $build_id_match[1],
+      'name' => $account->getAccountName(),
+      'pass' => $account->passRaw,
+      'op' => 'Log in',
+    ];
+    $url = $this->buildUrl($this->httpsUrl('user/login'));
+    /** @var \Psr\Http\Message\ResponseInterface $response */
+    $response = $client->post($url, [
+      'body' => http_build_query($post),
+      'http_errors' => FALSE,
+      'cookies' => $cookie_jar,
+    ]);
 
-    // Alter the form action to submit the login form through https.php, which
-    // creates a mock HTTPS request on HTTP test environments.
-    $form = $this->xpath('//form[@id="user-login-form"]');
-    $form[0]['action'] = $this->httpsUrl('user/login');
-    $edit = ['name' => $account->getAccountName(), 'pass' => $account->pass_raw];
+    $headers = $response->getHeaders();
 
     // When posting directly to the HTTP or HTTPS mock front controller, the
     // location header on the returned response is an absolute URL. That URL
@@ -158,6 +188,10 @@ protected function loginHttps(AccountInterface $account) {
     // automatic redirects normally performed by parent::curlExec().
     $maximum_redirects = $this->maximumRedirects;
     $this->maximumRedirects = 0;
+    $edit = [
+      'name' => $post['name'],
+      'pass' => $post['pass'],
+    ];
     $this->drupalPostForm(NULL, $edit, t('Log in'));
     $this->maximumRedirects = $maximum_redirects;
 
