To reproduce:

  1. Navigate to a Site node.
  2. Run a Reset password task.
  3. After the task completes, click on the Login to site link.
  4. This won't work as the URL isn't the subdirectory version, but move the domain prefix after the slash, and try again.
  5. The login process will redirect to the subdomain URL instead of the subdirectory URL, and the request will fail.

Further illustration:

colan@leopard[Fri 11 14:49]% curl -I https://example.com/site1/user/reset/1/1547236225/0s08V0zksIkEcWxFDFnEvW0uN0VQAU_klgJq0yXX-xY/login
[...]
location: https://site1.example.com/site1/user/1/edit?pass-reset-token=Dkq3-rINUzJnm3ZtZcVjdIXXeCjEur6LfyVPqX5pRIFiHjj2vytljLCZhTpTWHN2IO7RTh6onw
[...]

As can be seen above, it's adding a subdomain to the URL when it shouldn't.

This could be a problem with Aegir's subdirectory mode for Drupal 8 sites, which don't recognize $base_url, or a Drupal core issue such as #2753591: Fix mismatch of $base_url with Symfony request object.

Further digging is required.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

colan created an issue. See original summary.

memtkmcc’s picture

I have checked our support queue and as it turned out, it never actually worked for us, so we have always used a simple albeit rather silly workaround: adding standard subdomain alias like login.domain.foo so admins and users could log in via login.domain.foo/user instead of domain.foo/bar/user

colan’s picture

After some more research, I think #2 is the second part of a two-part problem that I haven't figured out yet.

The first part of the problem is that #3014381: Logins impossible on subdirectory sites needs to be implemented in D8. Setting the cookie path is easy; that's done the same way as in D7. However, setting the cookie domain needs to be done in the site's services.yml file like so:

parameters:
  session.storage.options:
    cookie_domain: '.example.com'

While this file is being included, I don't believe we ever create it. What's a good way to append the above to that file (generating it if necessary) during a Verify task?

  • colan committed d806d4a on issue-3025905
    Issue #3025905 by colan: Added the subdirectory cookie path for Drupal 8...

  • colan committed d806d4a on issue-3025905
    Issue #3025905 by colan: Added the subdirectory cookie path for Drupal 8...

  • colan committed 626769e on issue-3025905
    Issue #3025905 by colan: Set the cookie domain for subdirectory sites.
    
colan’s picture

I believe I did all that's necessary in Provision (in this branch), but now we need hosting_subdirs to write the subdirs.services.yml file we call here. That needs to be done in Hosting.

I tried, but couldn't get this to work, trying various alterations:

/**
 * Implements HOOK_post_provision_verify().
 */
function drush_subdirs_provision_verify() {
  //  drush_log("d: " . print_r(d(), TRUE));
  print_r('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\');
  //file_put_contents()
}

http://docs.aegirproject.org/en/3.x/extend/altering-behaviours/#develope... seems to be incorrect. We need to fix that as well, and add a section for how to do stuff in a Verify task.

ergonlogic’s picture

ergonlogic’s picture

It looks like the services.yml is being loaded via the $settings['container_yamls'] variable in settings.php. This appears to be an array, and so we should be able to provide both a generated file and allow site owner overrides with something like:

  /**
   * Load services definition file(s).
   */
  $settings['container_yamls'] = [
    __DIR__ . '/aegir.services.yml',   # Generated by Aegir.
    __DIR__ . '/services.yml',         # Managed by the site owner (optional).
  ];
ergonlogic’s picture

This patch generates an aegir.services.yml file, populates it with a cookie domain, and includes it in settings.php.

This appears to allow proper link URLs, pointing to the subdir (example.com/site1) in all internal links when logged in. However, when visiting the site anonymously, links drop the subdir, and thus fail. I suspect there's link construction is using some other replacement to $base_url (not cookie domain) for anonymous traffic.

Also, with #3034235: Use alias redirection target when creating goto/login link, we generate proper login/go-to links, with subdirs when enabled. However, the redirect appears to be duplicating the subdir segment in the link (e.g., http://example.com/site1/site1/user/...). So that's another challenge.

FYI, I'm working on this in the dev/fix-login-links branches of Hosting and Provision.

ergonlogic’s picture

It looks like we were constructing a $base_url variable to add our subdir segment, but not declaring it global.

I'm not certain this is the best solution, considering Removed base_url option from settings.php and related initiatives to remove $base_url. But it appears to work.

ergonlogic’s picture

That last fix appears to have resolved this issue.

Sorry, testing fail. I'd built the site on a D7 platform.

ergonlogic’s picture

We have confirmed that D7 subdir sites work properly on both Apache and Nginx. In addition, D8 sites work on Apache.
D8 sites on Nginx exhibit the following behaviour:

  1. Generating the onetime link works properly. We checked the task log, and the cached value.
  2. Clicking on the "Login" link appears to fail to log us in, since we get redirected to site1.example.com/site1/user/onetime...
    1. However, visiting the subdir site again shows that we are logged in.
    2. So, either Nginx or Drupal are redirecting to the subdomain URL (but notably keeping the subdir intact too)
      1. Drupal appears to be responsible for the initial redirect
  3. Drupal 8 (on Nginx only) is building incorrect internal URLs:
    1. Examining the Nginx access and error logs show that CSS, JS and images are failing to load (eg. nginx-site.do/core/themes/bartik/logo.svg)
    2. "Home" link URL: nginx-site.do (should be nginx-site.do/site4)
    3. "Contact" link URL: nginx-site.do/contact (should be nginx-site.do/site4/contact)

Drupal 8 appears to contruct its base URL by examining request headers, according to Drupal 8's API docs
Examining the headers from a (working) site on Apache, and comparing to a (non-functional) site on Nginx looks promising. Here are some notable differences:

|        HEADER         |            Apache            |            Nginx            |
| --------------------- | ---------------------------- | --------------------------- |
| CONTEXT_DOCUMENT_ROOT | /var/aegir/platforms/d8/web  |                             |
| CONTEXT_PREFIX        | /site2                       |                             |
| DOCUMENT_ROOT         | /var/www/html                | /var/aegir/platforms/d8/web |
| DOCUMENT_URI          |                              | /index.php                  |
| HTTP_HOST             | apache-site.do               | site4.nginx-site.do         |
| MAIN_SITE_NAME        |                              | site4.nginx-site.do         |
| PHP_SELF              | /site2/index.php             | /index.php                  |
| QUERY_STRING          |                              | q=                          |
| RAW_HOST              |                              | nginx-site.do               |
| SCRIPT_NAME           | /site2/index.php             | /index.php                  |
| SCRIPT_URI            | http://apache-site.do/site2/ |                             |
| SCRIPT_URL            | /site2/                      |                             |
| SITE_SUBDIR           |                              | site4                       |
ergonlogic’s picture

Setting the following headers appears to fix the problematic behaviour completely:

  • SCRIPT_NAME
  • PHP_SELF
  • SCRIPT_URI
  • SCRIPT_URL
  • HTTP_HOST

It's possible that a couple are redundant, but our current plan is to set all these in Nginx vhosts.

llamech’s picture

llamech’s picture

FileSize
1.4 KB

The attached patch adds the headers mentioned in #14 to the location block for index.php within the subdir vhosts for nginx.

In testing, this solves the login links problem and the other behaviours mentioned in #13.

However, we've noticed there are 4 other location blocks in the vhosts template where similar treatment is probably needed (e.g. for update.php, cron.php etc.). Our attempts to remediate these failed. This can be followed up in a separate issue.

It's worth mentioning that cron still works within the site.

llamech’s picture

Status: Active » Needs review

Should be fixed; needs testing.

memtkmcc’s picture

I will have to check and review this closely for Nginx part, but I believe there was a reason why we have added RAW_HOST and forced HTTP_HOST to match the site name $this->uri instead, not a current Nginx local $host

It was perhaps because we have then used in the global.inc some extra logic to handle sessions and other stuff to make it work:

/**
 * Detecting subdirectory mode
 */
if (isset($_SERVER['SITE_SUBDIR'])) {
  $site_subdir = $_SERVER['SITE_SUBDIR'];
}
if (isset($_SERVER['RAW_HOST'])) {
  $raw_host = $_SERVER['RAW_HOST'];
}

      if ($site_subdir && $raw_host) {
        $base_url = 'http://' . $raw_host . '/' . $site_subdir;
      }
      else {
        $base_url = 'http://' . $_SERVER['HTTP_HOST'];
      }

  elseif ($site_subdir && isset($_SERVER['RAW_HOST'])) {
    $domain = '.' . preg_replace('`^www\.`', '', $_SERVER['RAW_HOST']);
  }

memtkmcc’s picture

Too bad we never shared this BOA specific stuff with upstream, so it was never noticed nor followed up, while worked (mostly) for us.

llamech’s picture

Fixes for this, along with other subdirectory site fixes, are all in #3036890: Simplify subdir site installation. For simplicity, let's validate there.

  • llamech committed 648753f on 7.x-3.x authored by ergonlogic
    Issue #3025905 by llamech, ergonlogic: Add missing headers to Nginx...
  • ergonlogic committed 75f7a53 on 7.x-3.x authored by colan
    Issue #3025905 by colan: Added the subdirectory cookie path for Drupal 8...
ergonlogic’s picture

Status: Needs review » Fixed

We're merging fixes from #3036890: Simplify subdir site installation, which resolves this issue too.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

colan’s picture

colan’s picture