Skip to content

Instantly share code, notes, and snippets.

@jhedstrom
Last active June 24, 2021 12:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jhedstrom/5bc5192d6dacbf8cc459 to your computer and use it in GitHub Desktop.
Save jhedstrom/5bc5192d6dacbf8cc459 to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link

nephel commented Jan 13, 2016

good tip @jbickar - worked for me too

@asherry
Copy link

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
Copy link

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
Copy link

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
Copy link

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-
Copy link

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