Instantly share code, notes, and snippets.

Embed
What would you like to do?
Using the Behat Drupal Extension on sites with basic auth
<?php
/**
* Run before every scenario.
*
* @BeforeScenario
*/
public function beforeScenario() {
if ($basic_auth = $this->getDrupalParameter('basic_auth')) {
$driver = $this->getSession()->getDriver();
if ($driver instanceof Selenium2Driver) {
// Continue if this is a Selenium driver, since this is handled in
// locatePath().
}
else {
// Setup basic auth.
$this->getSession()->setBasicAuth($basic_auth['username'], $basic_auth['password']);
}
}
}
/**
* Override MinkContext::locatePath() to work around Selenium not supporting
* basic auth.
*/
public function locatePath($path) {
$driver = $this->getSession()->getDriver();
if ($driver instanceof Selenium2Driver && $basic_auth = $this->getDrupalParameter('basic_auth'))\
{
// Add the basic auth parameters to the base url. This only works for
// Firefox.
$startUrl = rtrim($this->getMinkParameter('base_url'), '/') . '/';
$startUrl = str_replace('://', '://' . $basic_auth['username'] . ':' . $basic_auth['password']\
. '@', $startUrl);
return 0 !== strpos($path, 'http') ? $startUrl . ltrim($path, '/') : $path;
}
else {
return parent::locatePath($path);
}
}
@jbickar

This comment has been minimized.

Show comment
Hide comment
@jbickar

jbickar Dec 20, 2015

Surprisingly tricky. The Googles led me to this gist, which actually didn't work for me. But setting:

base_url: https://username:pass@example.com

in behat.yml did. YMMV.

jbickar commented Dec 20, 2015

Surprisingly tricky. The Googles led me to this gist, which actually didn't work for me. But setting:

base_url: https://username:pass@example.com

in behat.yml did. YMMV.

@nephel

This comment has been minimized.

Show comment
Hide comment
@nephel

nephel Jan 13, 2016

good tip @jbickar - worked for me too

nephel commented Jan 13, 2016

good tip @jbickar - worked for me too

@asherry

This comment has been minimized.

Show comment
Hide comment
@asherry

asherry Jul 30, 2016

the problem I'm having is that after form submit, the page redirects and it doesn't keep the 'username:pass' part. Is that a problem with the site code or something I can do in the behat config?

asherry commented Jul 30, 2016

the problem I'm having is that after form submit, the page redirects and it doesn't keep the 'username:pass' part. Is that a problem with the site code or something I can do in the behat config?

@batigolix

This comment has been minimized.

Show comment
Hide comment
@batigolix

batigolix Mar 24, 2017

I'm using this method in FeatureContext.php to do basic auth login:

  /**
   * Run before every scenario.
   *
   * @BeforeScenario
   */
  public function beforeScenario() {
    $this->getSession()->setBasicAuth('boris', 'secret');
  }

batigolix commented Mar 24, 2017

I'm using this method in FeatureContext.php to do basic auth login:

  /**
   * Run before every scenario.
   *
   * @BeforeScenario
   */
  public function beforeScenario() {
    $this->getSession()->setBasicAuth('boris', 'secret');
  }
@shrop

This comment has been minimized.

Show comment
Hide comment
@shrop

shrop Feb 20, 2018

@batigolix, that is great ^^. I enhanced what you did by receiving the basic auth username and password with env vars. A bit better security so those don't have to get committed to repos.

/**
 * Run before every scenario tagged.
 *
 * @BeforeScenario
 */
public function beforeScenario() {
  $username = $_SERVER['BASIC_AUTH_USER'];
  $password = $_SERVER['BASIC_AUTH_PASS'];

  if (!empty($username) && !empty($password)) {
    $this->getSession()->setBasicAuth($username, $password);
  }
}

Run test

BASIC_AUTH_USER=<username> BASIC_AUTH_PASS=<passwprd> behat

shrop commented Feb 20, 2018

@batigolix, that is great ^^. I enhanced what you did by receiving the basic auth username and password with env vars. A bit better security so those don't have to get committed to repos.

/**
 * Run before every scenario tagged.
 *
 * @BeforeScenario
 */
public function beforeScenario() {
  $username = $_SERVER['BASIC_AUTH_USER'];
  $password = $_SERVER['BASIC_AUTH_PASS'];

  if (!empty($username) && !empty($password)) {
    $this->getSession()->setBasicAuth($username, $password);
  }
}

Run test

BASIC_AUTH_USER=<username> BASIC_AUTH_PASS=<passwprd> behat
@PapaGrande

This comment has been minimized.

Show comment
Hide comment
@PapaGrande

PapaGrande Apr 13, 2018

A small tweak to @shrop's code to make the basic auth credentials optional in the command line:

  /**
   * Run before every scenario tagged.
   *
   * @BeforeScenario
   */
  public function beforeScenario() {
    $username = (isset($_SERVER['BASIC_AUTH_USER']) ? $_SERVER['BASIC_AUTH_USER'] : NULL);
    $password = (isset($_SERVER['BASIC_AUTH_PASS']) ? $_SERVER['BASIC_AUTH_PASS'] : NULL);

    if (!empty($username) && !empty($password)) {
      $this->getSession()->setBasicAuth($username, $password);
    }
  }

PapaGrande commented Apr 13, 2018

A small tweak to @shrop's code to make the basic auth credentials optional in the command line:

  /**
   * Run before every scenario tagged.
   *
   * @BeforeScenario
   */
  public function beforeScenario() {
    $username = (isset($_SERVER['BASIC_AUTH_USER']) ? $_SERVER['BASIC_AUTH_USER'] : NULL);
    $password = (isset($_SERVER['BASIC_AUTH_PASS']) ? $_SERVER['BASIC_AUTH_PASS'] : NULL);

    if (!empty($username) && !empty($password)) {
      $this->getSession()->setBasicAuth($username, $password);
    }
  }
@ey-

This comment has been minimized.

Show comment
Hide comment
@ey-

ey- Oct 22, 2018

In case someone has the same issue.
Recently we had the following Exception using the snippet from @PapaGrande.

 Behat\Testwork\Call\Exception\FatalThrowableError: Fatal error: Call to a member function send() on null in /var/www/vendor/dmore/chrome-mink-driver/src/ChromeDriver.php:1330

This was caused by a not started session prior to using setBasicAuth.

The solution here is to check if the session is started, and if not start it. Resulting into the following:

 /**
   * Run before every scenario tagged.
   *
   * @BeforeScenario
   */
  public function beforeScenario() {
    $username = (isset($_SERVER['APACHE_BASIC_AUTH_USER']) ? $_SERVER['APACHE_BASIC_AUTH_USER'] : NULL);
    $password = (isset($_SERVER['APACHE_BASIC_AUTH_PASS']) ? $_SERVER['APACHE_BASIC_AUTH_PASS'] : NULL);

    if (!empty($username) && !empty($password)) {
      $session = $this->getSession();
      if (!$session->isStarted()) {
        $session->start();
      }
      $session->setBasicAuth($username, $password);
    }
  }

ey- commented Oct 22, 2018

In case someone has the same issue.
Recently we had the following Exception using the snippet from @PapaGrande.

 Behat\Testwork\Call\Exception\FatalThrowableError: Fatal error: Call to a member function send() on null in /var/www/vendor/dmore/chrome-mink-driver/src/ChromeDriver.php:1330

This was caused by a not started session prior to using setBasicAuth.

The solution here is to check if the session is started, and if not start it. Resulting into the following:

 /**
   * Run before every scenario tagged.
   *
   * @BeforeScenario
   */
  public function beforeScenario() {
    $username = (isset($_SERVER['APACHE_BASIC_AUTH_USER']) ? $_SERVER['APACHE_BASIC_AUTH_USER'] : NULL);
    $password = (isset($_SERVER['APACHE_BASIC_AUTH_PASS']) ? $_SERVER['APACHE_BASIC_AUTH_PASS'] : NULL);

    if (!empty($username) && !empty($password)) {
      $session = $this->getSession();
      if (!$session->isStarted()) {
        $session->start();
      }
      $session->setBasicAuth($username, $password);
    }
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment