Hi,

This seems to be a bit of an edge case but when I try to install Drupal 8 (the latest in the codebase from git) on an Amazon AMI (their vanilla ami instance w/ PHP 5.3.27), the installation seems to go well. But as soon as I try to log into the site (fill out the form, click 'log in'), I get a WSOD and my error log shows the following error:

PHP Fatal error: Call to undefined function drupal_session_regenerate() in /var/www/drupal8/core/modules/user/user.module on line 1148, referer: http://d8test.domain.com/.

To note, I do *not* get this issue locally (which runs Acquia Drupal w/ PHP 5.3.18) and neither to my colleagues (one of whom runs Ubuntu - neither to the test bots though I don't know the OS they are running).

Looking through, I see that user_login_finalize calls on drupal_session_regenerate(). And that function exists in session.inc. But the only way for that function to get included in a web request is by the Cookie class which seems like it be able to come through from AuthenticationManager. In IRC, @tim.plunkett suggested that only HTTPBasic might be firing (and not Cookie) hence the continued issue (though I'm not sure how to get it to fire up Cookie as well :)).

I'm not entirely sure on how else to go about resolving this issue so any suggestions are much appreciated. I'm happy to provide any other details to help with this :)

CommentFileSizeAuthor
#2 session-2073041-2.patch1.31 KBtim.plunkett

Comments

btmash’s picture

Category: support » bug

A *huge* thanks to @tim.plunkett putting me on the right path. I finally figured out the cause of the issue (though I think there is more need of a resolution hence changing to a bug report). In my scenario, since it was on a public server, we had placed the site behind basic authentication by apache. From the Drupal side, Drupal has a pluggable authentication system and it comes with 2 of them out of the box: HttpBasic and Cookie.

D8 attaches both the HttpBasicauth and Cookie authentication providers to the system (runs in order of HttpBasic followed by Cookie). Within the queue, if any auth passes, it breaks out of the loop and continues. In this case, since HttpBasic runs first and passes, it doesn't get around to Cookie (which actually adds session.inc) and thus, it fails in the end.

Ultimately user_login_finalize requires for a session to be present. So it seems like Cookie needs to have the highest priority and run first or each of the providers need to include session.inc. I can foresee dev sites (not just mine!) being password protected so suggestions on how to approach a patch would be very helpful.

tim.plunkett’s picture

Status: Active » Needs review
Issue tags: +Needs tests
StatusFileSize
new1.31 KB

In D7, session.inc was always loaded.
If user_login_finalize() always calls it, it might make sense for AuthenticationManager::authenticate() to load session.inc for us.

I'm not sure if this is testable, but we should try.

btmash’s picture

Status: Needs review » Needs work

That is certainly a much simpler solution than including line in every authentication provider :)

For testing...I was trying to figure out an appropriate way to test something like this within simpletest. We do technically have access to http://php.net/manual/en/features.http-auth.php so I'm assuming we would have a subscriber that adds the authentication to every page that it can pass through (though how well it plays with existing tests is another issue entirely).

In any event, I just tried out the patch. While the WSOD is now gone (yay!), authentication technically passed due to HTTPBasic (and HTTPBasic may just be a simple user/pass to access the site). As a result, it never gets around to Cookie which would do a proper check via the user login form and thus the user does not get logged in.

btmash’s picture

Looking through the implementation of this, I see the HttpBasic has a priority of 100 while Cookie has a priority level of 0. As a result, HttpBasic would run first at part of the authentication chain (though it isn't exactly a chain as checking which auth rules apply boils down to which auth provider passes first). Which...leads me to a few questions.

I'm going to give an example of the LDAP module for D6/D7. It has a bypass check for user 1 whereby it will use any other Drupal-based authentication (instead of ldap) when dealing with the superuser. All other users have the option to only get checked via both Drupal/Ldap or just ldap.

In D8, it doesn't seem like those would really be possible (atleast at a first glance). We either need to have extra rules (as in applies if we were dealing with ldap) or figure out how to have a proper chain to check through all authentication providers (or not. maybe this makes less sense).

In any case, one possible approach I see atleast around this issue is to actually make the HttpBasic provider become part of a new core module that implements the same class (or move it out to contrib). It doesn't need to be running on every site automatically and people enable the module if they need to.

Crell’s picture

There is already an issue to move HttpBasic to its own module: #2041885: Move HTTP basic authentication provider to a separate module

I'd very much prefer if we could run auth after routing and simplify the back and forth here, but we need language negotiation before routing and auth before language. :-(

btmash’s picture

@Crell, thank you for pointing me towards that issue - I've issued a patch in there for a faster resolution (of that task).

With that said (and before we close this issue closed out for either being a duplicate or by design), I have a few questions to go with all of this: How should a system where we (can) have multiple authentication systems (we have two in core and will have several others in the future) behave? Is the Drupal authentication system chainable? And why (regardless of answer)?

Crell’s picture

The presumed use case is that pretty much everything will want to allow cookie auth, but only a small subset will want to allow Http Basic, Http Digest, or OAuth[2]. (Mainly entity routes via rest.module, but potentially others.) So machines will talk to a small subset of routes using non-cookie auth, while humans use cookie auth.

In practice, I don't know that there's much of a use case for a single route actually using multiple auth methods. We support it, but I don't expect it to be common. And the support is limited, because only one auth provider can issue a challenge for missing credentials (redirect to a login page for cookie, issue a 401 Auth Required for Basic, or whatever it is OAuth does). So I don't think a user hopping between auth mechanisms in a single session is going to be supported, as I see no use case for it.

btmash’s picture

Status: Needs work » Fixed

Thanks for the explanation - it sounds fairly reasonable to me (along with others that I've talked with that implement their own auth backend.

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

Anonymous’s picture

Issue summary: View changes

More clarification.

shivanshuag’s picture

I am porting securesite module to d8 and I have run into the same problem. The module, along with other funcationality, allows to add basic auth on some secured pages of the site. The way this is handled is by checking the header for basic auth credentials if securesite module is enabled. If basic_auth module is enabled, and the request header has basic auth credentials, the user_login_finalize does not set the session.

shivanshuag’s picture

Status: Closed (fixed) » Active

So it seems that there is no way to set a session when request has basic auth credentials in its header and basic_auth module is enabled. Take a use case when I want to set a session for an authenticated user by basic auth and not user login form.

If basic_auth module is enabled and the request has basic auth credentials, the BasicAuth Authentication Provider will be used to authenticate the user since it has higher priority. It does not initialize a session. Even if you register an event subscriber and set a session for authenticated user, AuthenticationEnhancer class resets it to anonymous session. AuthenticationEnhancer class checks for permitted AuthenticationProvider, which is by default the AuthenticationProvider with lowest priority i.e. Cookie. You can also set permitted AuthenticationProvider by '_auth' key. For any authentication which is not done by permitted authentication provider, the session is reset to anonymous by this class. The '_auth' key in the route but this can be set only for some routes. What if I want this for all the routes? So, '_auth' key is out of option.

From above it seems that making a 'default' authentication provider which has higher priority than basic_auth should solve the problem. This auth provider will be used on all the requests and the session set by it will not be reset to anonymous by AuthenticationEnhancer class. But then if it has higher priority, it wont be default(default auth provider is the one with lowest priority). If you register your own AuthenticationProvider, it will have to have priority greater than Cookie AuthenticationProvider(because cookie auth provider applies on all the requests and an auth provider with lower priority will never be used) and thus can never be a default auth provider. So, default authentication provider can never be other than cookie.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dpi’s picture

Status: Active » Closed (outdated)

Drupal 8 has changed considerably since this issue was last addressed. There isn't even a drupal_session_regenerate anymore.

If anyone still has this issue, please speak up and resurrect.