Problem/Motivation
Drupal login requires user browser cookie support. However, in the case that a user does not have cookies enabled and attempts to log in, no error message is given. Instead, the user is returned to the /user/{uid}
page with 403 error code. As well as being a bug, the lack of cookie notification constitutes a key usability barrier in that users who hit the bug have no cue as to what is needed in order to log in.
Related issue at install time: #791004: Installer does not warn the user that cookies must be enabled with the correct cookie domain (and fails when they aren't).
Other PHP applications by way of comparison:
Wordpress:
Code is in http://core.svn.wordpress.org/trunk/wp-login.php. Prior to login, a test cookie is set:
//Set a cookie now to see if they are supported by the browser.
setcookie(TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN);
if ( SITECOOKIEPATH != COOKIEPATH )
setcookie(TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN);
A hidden element is added to the login form:
<input type="hidden" name="testcookie" value="1" />
On login attempt, if the testcookie flag is set but the test cookie is not present, an error is raised:
// If cookies are disabled we can't log in even with a valid user+pass
if ( isset($_POST['testcookie']) && empty($_COOKIE[TEST_COOKIE]) )
$errors->add('test_cookie', __("<strong>ERROR</strong>: Cookies are blocked or not supported by your browser. You must <a href='http://www.google.com/cookies.html'>enable cookies</a> to use WordPress."));
Joomla: Reportedly doesn't provide user feedback on cookie failure; see this forum post.
Symfony: Cookie handling doesn't appear to include a test for browser cookie support.
Proposed resolution
The proposed patch takes the following approach:
- Add a querystring parameter "state=check_logged_in" upon login form submission.
- On Kernel Request, if the parameter exists and the user is not actually logged in, then we know they don't have cookies enabled so we set a form error.
Remaining tasks
- Additional test coverage,
and/or remove "Needs tests" tag Drupal\Core\EventSubscriber\MaintenanceModeSubscriber::checkUserCookies
should be moved to a better appropriate ServiceSubscriber such as:Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber
. For now, thecheckUserCookies
has nothing in relation with theMaintenanceMode
Discuss about the comment of #217 of user_login_form_submit hook. What was the purpose should we keep it?The current patch was an initial draft. Several other possibilities have been suggested since, with no clear consensus as yet. #145 includes a reasonably current summary of options. Latest comment from D8 maintainer catch: "I don't like either the double redirect option, or the runtime check on every page here, but neither do I have any better ideas - would be good to get some feedback from others."#138 reports the following issue with the patch: "if the user logs off and uses the browser's history or back button to return to the page containing the "state=loggedin" query, then the cookie warning message is displayed when it shouldn't be. It would be possible to reword the message to allow for this possibility, absent a better solution."#123: "some of the information in this issue needs to be added to user_init() in a comment if we go for this option."The current patch generates two errors. From #160: "Those two failures look like they're specific to the solution here (probably code that expects a specific URL after logging in and therefore gets confused by the new ?state=loggedin). So not worth fixing unless this is the actual solution we're going with."Given that this is a common need that's been addressed in many other PHP applications but not in Drupal, we'd do well to look around. Some information is above in the issue summary. More research welcome.
User interface changes
Users attempting to log in will receive an error message if they don't have cookies enabled.
API changes
Modifies the user login process by adding a query string "state=loggedin" and testing for it during KernelEvents::REQUEST.
Original report by anders
since drupal relies on cookies for logging in, not warning the user if the cookie is not allowed is plain old stupidity.
We need a warning to regular user (on an already installed Drupal site) that they need to enable cookies to be able to log in on the site.
Right now nothing is displayed if cookies and not enabled and the user have not clues as to why.
We did have a patch (but it need a reroll), and a test.
Comment | File | Size | Author |
---|---|---|---|
#300 | 2021-12-22 22_09_24-Window.jpg | 7.44 KB | cosolom |
#293 | Screen Shot 2021-06-25 at 2.34.29 pm.png | 71.79 KB | larowlan |
#279 | 2946-279.patch | 10.52 KB | quietone |
#256 | 2020-12-12-130826-2946-255-one-time-login.png | 224.69 KB | michaellenahan |
#256 | 2020-12-12-130732-2946-255-user-login.png | 203.54 KB | michaellenahan |
Issue fork drupal-2946
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
Dries CreditAttribution: Dries commentedMaking this a feature request instead of critical bug report. Tss.
Comment #2
JonBob CreditAttribution: JonBob commentedComment #3
katok CreditAttribution: katok commentedComment #4
bdragon CreditAttribution: bdragon commentedMarking as duplicate of http://drupal.org/node/137678
Comment #5
dwwThere's some useful discussion over at http://drupal.org/node/137678 but we should continue with this, the oldest issue, as the active one that needs to be resolved.
Comment #6
beginner CreditAttribution: beginner commentedOffering a user to log-in in a situation where the login will automatically fail can safely be considered a bug.
Comment #7
chx CreditAttribution: chx commentedThis is a bit tricky but I figured it out. Messages do not work here too well because you get a new session on every single page. So we redirect you to a help page if there are no cookies, but not everytime.
Comment #8
chx CreditAttribution: chx commentedAlso http://drupal.org/node/137678
Comment #9
snufkin CreditAttribution: snufkin commentedtrying to log in now brings to a page with a brief description about the missing cookie support. It could be enhanced later, but with this the bug is solved for now.
Comment #10
chx CreditAttribution: chx commentedYeah but as comment cookies need path set so do these. It's not trivial under testing because it's only a problem if you land on the non-root page and try to log on another page.
Comment #11
beginner CreditAttribution: beginner commentedErrr... can you explain patch #10. Is it the right issue?
As to patch #7, this is a patch my poor brain can understand. I am satisfied that it is a good approach.
But we are only at the stage of reviewing the concept. #10 has not been reviewed, and #7 is not RTBC in any case: if the patch works and is accepted, at the very least the message on the no_cookie page should be improved (poor grammar, not enough information). It's good enough for testing, so it's good enough for now, but it will have to be improved before we can set it RTBC.
Comment #12
beginner CreditAttribution: beginner commentedSpeakind about the documentation on the no_cookie page, see #6 here:
http://drupal.org/node/137678#comment-271450
I personally think it's a bit too much, but it can give some ideas. What do you think?
Comment #13
drewish CreditAttribution: drewish commentedyeah #10 looks like the wrong patch.
Comment #14
Chris Johnson CreditAttribution: Chris Johnson commented#10 looks like the completely wrong file got uploaded. Yoohoo, CHX...
Comment #15
beginner CreditAttribution: beginner commentedI think we know that, by now.
What I would like to know, is the answer to #12, so that we can move ahead...
Comment #16
snufkin CreditAttribution: snufkin commentedroll a patch with this text, so we can check it ;)
I think this could be committed though, its only the cosmetics of the text we try to fix now, the issue itself is solved.
Comment #17
chx CreditAttribution: chx commentedWell, #10 and #7 wanted to differ only in the path component and I indeed upped the wrong version. About the text, it's a placeholder, someone else will write the text, it's not my cup of tea.
Comment #18
chx CreditAttribution: chx commentedAlso, about the linked comment. One, it misses firefox, opera, safari and ie7. Second, the big problem here is that it's not necessarily the browser that kills your cookies -- it can be your personal firewall (zonealarm is a notorious offender), it can be a bad proxy in the way etc etc
Comment #19
snufkin CreditAttribution: snufkin commentedLet's have this committed, and I will open a new issue about the text. This way we keep this thread to the technological issue, and that to discuss the helptext. How about it?
Comment #20
nedjoNice work chx.
Needed this so turned it into a D5 contrib module, http://drupal.org/project/cookie_check. Here's the message I used:
Comment #21
salvisApplied nedjo's text and rerolled for HEAD.
Unfortunately, user/no_cookie gives me "Page not found."
Comment #22
nedjoThanks for the updated patch.
Did you refresh your menu item cache? Since the module is already enabled, you'll need to do so to get the new menu item available. You could try e.g. disabling then reenabling a module.
Comment #23
salvisAh, yes, clearing the cache has made it work. Thanks!
Comment #24
catchThis looks good to me. Tested, works great.
Comment #25
catchActually no, "Cookie problems" isn't a great title - implies that Drupal's having problems rather than the user's browser.
Would suggest "Please Enable Cookies" or something like that.
Comment #26
salvisOk, I've changed the title to 'Please Enable Cookies!'
Comment #27
sunSlightly changed wording.
Comment #28
catchLooks good to me.
On a side note, I tested the patch in IE7 to avoid affecting tabs in firefox. Then left cookies off. Then cleared my D6 install and later wanted to test some js in IE7. How much did I miss this patch the first couple of times I tried to log in! Only took five seconds to work out what was going on in this case, but a big improvement.
Comment #29
RobRoy CreditAttribution: RobRoy commented- Drupal core paths use dashes instead of underscores...should be user/no-cookie.
- Might as well just return t(...) instead of setting an unneeded $text variable.
Comment #30
sunComment #31
bjaspan CreditAttribution: bjaspan commentedsubscribe
Comment #32
sunComment #33
bjaspan CreditAttribution: bjaspan commentedI suggest that user_no_cookie() should return theme('user_no_cookie') so sites can override this hard-coded text.
Comment #34
sunComment #35
bjaspan CreditAttribution: bjaspan commentedNew patch. The only change here relative to #30 is the theme_user_no_cookie() instead of hard-coding the text.
This bug has always annoyed me but perhaps it is too late for D6. I think there are valid outstanding questions:
1. The default text (http://drupal.org/node/137678 has something but it isn't done).
2. Should the cookie path really be "/" and not session.cookie_path?
3. Probably others.
Comment #36
bjaspan CreditAttribution: bjaspan commentedOh, and how long should the login_check cookie survive and/or should it use some kind of unique value to try to identify if the login_check cookie that is coming back is the one that just got set?
I think while testing in IE6 I observed that by turning off cookies I was only turning off accepting new cookies, not disabling the delivering cookies I already had. So a login_check cookie I received while testing yesterday was being delivered even though I had "turned off cookies" so my new session cookie wasn't being accepted. The result was that login failed but I did *not* get redirected to the no_cookie page b/c the login_check cookie was delivered. This could make debugging login problems even harder, so we need to understand this before committing.
Comment #37
chx CreditAttribution: chx commentedThe cookie should be deleted after logging in.
Comment #40
Gábor HojtsyPatch looks reasonable. I am not sure, but maybe we can expalain how cookies can be set to be accepted in simple terms (ie. "turn off private browsing" if this is common enough among browsers).
http://drupal.org/node/137678 has good source data for a documentation page to put up. While that should not be included in Drupal itself, and it might not be wise to direct innocent users to drupal.org, it would be a good docs page. :| Thinking out loud.
Comment #41
salvisGábor, please don't try to save the world with this patch! There are countless reasons why cookies might not go through, beyond what the browser does, and every browser uses its own terminology anyway. I've never heard of "private browsing" -- would you really want to take responsibility for whatever could happen if a user "turns off private browsing" on some unknown system? Helping the user to solve the problem is way beyond what Drupal can do.
The intent of this humble patch is to diagnose the problem, and this alone will put us miles ahead of where we are now, where the user has absolutely no clue about why his password is accepted, but he still doesn't get access.
Users who have cookies turned off, will usually know how to turn them on, because the situation comes up regularly on all sorts of sites -- but they need to know what the problem is!!!
Please excuse me if this comes accross a bit too strong, but I'm desperate about this...
Comment #42
Gábor HojtsyOK, let's fix chx's concern at least first.
Comment #43
chx CreditAttribution: chx commentedA lot better patch. Instead of session.inc , I patched
drupal_anonymous_user
. Same: if your system can't hold cookies then on the page load your cookie will be set but it's only available on the next page load. I have adjusted the cookie domain to the session cookie domain, too. And now I delete it inuser_login_submit
.Comment #44
Gábor HojtsyActually, drupal_anonymous_user() is used to as generic anonymous user object fetcher function (I have seen it used as an $account parameter generator for access checks for example). So I don't think it is a good idea to build side effects into it.
Comment #45
chx CreditAttribution: chx commentedOK then. it's still better than the older ones because we now patch both places where anonymous user can happen.
Comment #46
chx CreditAttribution: chx commentedDoh.
Comment #47
chx CreditAttribution: chx commentedAdjusted user_no_cookie function to use the relevant domain.
Comment #48
chx CreditAttribution: chx commentedAdded domains to the setcookie .
Comment #49
salvisYes, now it works perfectly, including deleting the cookie upon log-in. Thanks!
Comment #50
Dries CreditAttribution: Dries commentedI'm not really sure this is worth fixing. Looks a bit crufty to me.
Comment #51
beginner CreditAttribution: beginner commentedThis is a huge useability improvement, and makes Help Desk workers happier :)
++ 1 for the patch.
Comment #52
catch+1 from me as well. We get regular e-mails from people saying "I can't log in!!11!!" and if this reduces them by even 5% that'd be great.
Comment #53
salvisI run with paranoid firewall and browser settings, and I can't remember encountering a site that didn't tell me I needed to enable cookies when it requires them, except for Drupal sites, that is.
Drupal really, really stands out (negatively!) in that respect...
Comment #54
dww+1 from me, too. This is not cruft. This is a frequent source of support effort on nearly every Drupal site (certainly all the ones I have personal experience with). Almost all sites on the net are smart enough to diagnose this problem and warn you when you can't log in because your browser is not accepting cookies. Drupal should, too. Quick visual inspection of patch #48 looks good to my eyes.
Comment #55
soxofaan CreditAttribution: soxofaan commentedMaybe I am missing something, but why is it needed to do a "setcookie('drupal_login_check', ..."?
If cookies are disabled, $_COOKIE will always be empty and if cookies are enabled, $_COOKIE will have at least one entry with the session name (except for first visit).
So in user_login_submit()
if (count($_COOKIE) == 0)
should be equivalent with theif (!isset($_COOKIE['drupal_login_check']))
from patch #48.If so, there is no need to add "cruft" to session.inc and there is no "cruft" needed for deleting the 'drupal_login_check' cookie.
See attached patch. I tested it and it behaves the same as the patch from #48.
(But I could be wrong about the assumption that $_COOKIE will always be non-empty after first visit when cookies are enabled.)
Comment #56
salvisInteresting thought, but can we be sure that the browser doesn't send any cookies at all, if they're currently turned off? Or could it be sending old cookies?
Maybe we do need the 'drupal_login_check' cookie, but with a very short lifetime? Or add a timestamp so that we can verify that we're getting a fresh cookie?
Comment #57
chx CreditAttribution: chx commentedI re-RTBC #48 -- I would never rely on an empty cookies array. In theory it's not even impossible that this check fails, ie. the browser holds the login checker cookie and not the session one... but it's imo much better than relying on an empty cookie array.
Comment #58
dwwI agree #48 is more reliable and therefore superior.
Comment #59
soxofaan CreditAttribution: soxofaan commentedFair enough. But you can never trust a/every browser. You could even create a browser so that #48 would fail.
This issue is a usability issue, so we should solve it for most use cases/standard browsers, not all imaginable exotic corner cases. The point is to find the right balance between adding cruft and solving the issue for enough people/cases.
It would be nice to have some real life examples that would show that #55 is significantly inferior.
I just wanted to address the cruftiness concern of Dries.
Comment #60
soxofaan CreditAttribution: soxofaan commentedOn a slightly different note: why deleting the 'drupal_login_check' cookie in patch of #48?
Some modules might want to check if cookies are enabled. The CAPTCHA module (of which I'm co-maintainer) for example requires sessions (and by consequence cookies) to work properly. It would be nice if there would be a standard drupal way of detecting if cookies are enabled.
So why not renaming 'drupal_login_check' to 'has_cookie' (just like the 'has_js' cookie) and not deleting it.
Just thinking out loud.
Comment #61
salvis@soxofaan: see #36...
(this problem may apply to the has_js cookie, too!)
Comment #62
Gábor HojtsyLooks like last minute campaigning did not get Dries' favor, so moving to the 7.x queue, in the hopes that it will be getting in early in the cycle.
Comment #63
Gábor HojtsyComment #64
salvisWell, now that soxofaan has successfully kept this patch from getting into D6, maybe we can pick up the pieces and put #48 into D7?
Comment #65
Anonymous (not verified) CreditAttribution: Anonymous commented+1 to make something like this a core feature.
Another way to look at this might be to stop the user from logging in if the person doesn't have cookies enabled before they actually login. Or just a standard text message on the login page stating that cookies must be enabled to login.
Edit: rewrote this post a bit.
Comment #66
Dries CreditAttribution: Dries commented* The patch does no longer apply.
* Is this something we can write a test for?
Comment #67
Dries CreditAttribution: Dries commented* The patch does no longer apply.
* Is this something we can write a test for?
Comment #68
chx CreditAttribution: chx commentedDries -- no, because you can not even get to test page if your install does not keep cookies and also the test path is server->server meanwhile the request path is browser->firewall->ISP proxy->whatever->server.
Comment #69
nedjoI made a D5 module based on this patch, http://drupal.org/project/cookie_check
Users reported a bug, possibly limited to IE7:
drupal.org/node/242060
The bug may be due to some change I made in adapting the patch but we shd try to reproduce before applying this.
Comment #71
Frank Steiner CreditAttribution: Frank Steiner commentedI shouldn't complain as I didn't do any work to solve this issue, but it's hard to understand why there has been a patch that solves this problem for almost a year and it still hasn't been added. I often have user coming to me and complaining that login doesn't work and it's always because they haven't enabled cookies for this site.
Sometimes it seems a bit strange how difficult it is and how long it takes to get such basic things to be added to drupal. Every other CMS we use at the university does have this cookie warning feature...
Comment #72
catch@Frank, the patch was posted in May. Count the number of people who've tested it since then, there's your answer. If you tested it, and it worked, why didn't you post back here to say so?
Comment #73
Frank Steiner CreditAttribution: Frank Steiner commentedI can only apply it to 6.x and I learned that almost no one cares about this because everything is patched in HEAD and maybe backported afterwards, maybe not.
It works fine in 6.x for my site, but I don't see how this helps :-(
> the patch was posted in May
That's not really true. The patch is from January, but it has been ignored until it didn't apply anymore, see #66. Then chx made the new version which just differs in the context lines, not in the patch code itself. And then this has again been ignored until it didn't apply anymore. And now it looks like chx is not interested in making another version of the patch (which might again be ignored for months?).
According to http://testing.drupal.org/pifr/file/1/user-no-cookies-2946-67.patch it was received for testing on November 8th. So I wonder what happened between May and November. It seems likely that a patch written in May for HEAD doesn't apply in November anymore.
Same for 6.x, but it was again just adjusting the context lines. If I had 7.x I would try to correct the patch, but I've no idea (yet?) how this testing stuff works and what must be done to make a patch get into this testing.
So, I don't know what I can do more to say "Works great in 6.x". But you're right, I could have said that earlier!
Comment #74
nedjoHere is an updated and reworked patch.
Changes:
* Move the cookie checking to a validation handler, alongside the three existing user login validation handlers.
* Set a form error rather than forwarding to a separate page.
* Default to $_SERVER['HTTP_HOST'] if ini_get('session.cookie_domain') is empty.
These changes:
* Address changes in HEAD that made the previous approach no longer work.
* Increase flexibility--sites can alter or remove this validation.
* Avoid creating a new menu item.
* Prevent the potential confusion of users being at or returning to a page with a message saying their browser doesn't support cookies after they have enabled cookie acceptance from the domain.
* May increase usability by returning users to the login form they used.
Comment #75
nedjochx noted in #7 that messaging is potentially problematic in that, without cookies, data don't persist in the session.
In this case we remain on the same page and so messages set in the $_SESSION variable remain available for rendering; the form_set_error() call works.
This would break if e.g. a contrib module set a validation handler that called drupal_goto(). I think we can live with that though. Handling this as validation feels the cleanest.
Comment #76
nedjoWith patch...
Comment #78
nedjoI ran tests locally and didn't get the reported error. Setting back to 'code needs review'.
Comment #79
Owen Barton CreditAttribution: Owen Barton commentedPatch applies and generally looks good. A couple of notes:
We may want to consider the help text "It seems your browser does not accept cookies." seems like slightly odd phrasing perhaps. Also, I wonder if it would be good to link to some generic "what the heck are cookies" page (e.g. on wikipedia?).
This looks a little nonstandard also - the function below it (which is equivalent) starts as "A validate handler on the login form....".
Comment #80
salvisPeople who don't know what cookies are, are unlikely to have this problem. And if they do, then this is not the first site where they encounter the problem, and they need to get help anyway. It's quite likely the first site that fails to provide any indication about the nature of the problem though... 8-(
What we desperately need is a terse message that tells those who know, what the problem is, so they can immediately start work on fixing it rather than having to search for why login attempts might be ignored.
There can be many other reasons besides the browser, so the messages must not be more specific than it can rightfully be.
Please propose improved wording for the comments.
Comment #81
Frank Steiner CreditAttribution: Frank Steiner commentedI think it's more important to have any hint on what's going wrong than just beeing unable to login. There are pages explaining how to activate cookies, but they usually miss my browser anyway or are for Netscape 6.x or sth.
Comment #83
beginner CreditAttribution: beginner commentedThis affects the installer as well. Some people have cookies turned off by default, but have a whitelist of web sites where it's accepted.
When installing a new site, the new domain may not yet be in the whitelist.
In such conditions, it is impossible to install Drupal at all, but the the warning given make it sounds like it's a sql issue, which is very confusing and does not help finding the solution.
The following critical installation issues are caused by the absence of cookie:
#234539: Critical SQL error in installer with {menu_router}
#261148: menu_masks variable is empty (race condition)
#280015: cannot install drupal - menu_router error
Comment #84
richard.e.morton CreditAttribution: richard.e.morton commentedI agree, this is a bug from the users point of view (the only view that counts).
Cookies being disabled/not-supported should be gracefully handled. a fix should also (ideally) be backported to 5 and 6 also.
subscribing.
Comment #85
robeano CreditAttribution: robeano commentedComment #86
robeano CreditAttribution: robeano commentedFixed domain name display from nedjo's patch in comment #76
Comment #87
beginner CreditAttribution: beginner commentedAs an example of how absence of cookies are handled elsewhere, turn off cookies and visit this web site:
http://www.expedia.com/
Can't miss the (scary) warning!
Comment #88
beginner CreditAttribution: beginner commentedAnother example:
A simple warning is given here (again, visit with cookies turned off).
http://www.autism-society.org/site/PageServer?pagename=asa_home
Comment #89
xmacinfoI think it's time to get the fix for this 2003 request rolling.
I've block cookies, log out of the fresh Drupal 7 head install and applied the patch. As soon as I try to log in, I get the proper warning "It seems your browser does not accept cookies. To log into this site, you need to accept cookies from the domain example.com".
Are there some issues which would prevent this patch from being committed?
Comment #90
chx CreditAttribution: chx commentedHoly Batman, my patch is not in yet????
Comment #91
xmacinfoBatman is not holy. :-)
I guess we should grab webchick today for the code sprint. I've have not seen her yet this morning.
Comment #92
nedjoSince this patch is limited to responding to attempted logins using login forms, it doesn't yet address two other needs:
1. We need to issue a warning at install time what cookies are required. (User does not log in using the login form.)
2. There are other cases where cookies may be required although users are not logging in. E.g., functionality that uses cookies to track anonymous users.
Still, it's probably a good first step. It handles the most pressing issue in Drupal core and could later be extended or modified to address these other needs.
Comment #93
xmacinfoI think it would be best for you to create two new issues for:
:-)
Comment #94
alexanderpas CreditAttribution: alexanderpas commentedhook_requirements() of the user module?
new hook?
Comment #95
webchickWe need tests for this. I check with cwgordon7 and he said it should be possible to override curlConnect() in your test case.
Comment #96
alexanderpas CreditAttribution: alexanderpas commented@webchick
any updates weither this is testable or not?
Comment #97
webchickI relayed what I was told. There's a testing sprint going on this weekend, so plenty of people to ask in #drupal. :)
Comment #98
xmacinfoCan we just commit and add the test later?
Most of the experienced core commiters have already worked on this issue without raising the test issue.
Comment #99
Weka CreditAttribution: Weka commented++ 1 Bug Report
++ 1 Usability Issue
++ 1 Expand this issue to cover other forms in addition to user_login
Any functionality that requires the presence of a cookie should alert the user if the cookie is absent.
Many thanks to chx and nedjo for addressing this issue and contributing to a solution.
As nedjo correctly pointed out in #92
The issue #502816: Anonymous users do not see status messages is one of those examples.
I was very surprised reading Dries comments on this issue.
Comment #100
salvisNo, don't expand, commit!
As chx explained in #68, SimpleTest is close to useless for this. We'd test the behavior with one "browser" (that doesn't even exist in the real world) in an extremely unrealistic environment. The real world is much more complex and we won't know whether it works out in the wild until we let it loose.
Do we really want Drupal 7 (!) to become known as the one CMS/Framework that still, in 2010, doesn't even make an attempt at detecting this obvious stumbling block? What a cool way to fingerprint Drupal sites! :-(
If this had been committed in spring we'd have half a year's worth of almost-real-world testing by now. But we're still dabbling — it's pathetic...
Comment #101
xmacinforobeano patch in #86 still applies. I'm requesting a re-test of his patch.
As per other comments I'm putting this back to RTBC. :-)
Comment #103
xmacinfoThe patch fails. Needs a reroll.
Comment #104
bleen CreditAttribution: bleen commentedHere is a straight reroll of the patch in #85
I saw the node id of this issue and was sure I was misreading. I'm amazed this hasn't been addressed since Dries reported it in 2003
Comment #105
sunShouldn't the cookie validator run first, so the potential error message appears first?
"Form validation handler to ..."
These two lines need an inline code comment (each), explaining what is being done here.
Trailing white-space.
Lastly, we need a test for this functionality.
This review is powered by Dreditor.
Comment #107
mcrittenden CreditAttribution: mcrittenden commentedSub.
Comment #108
coderintherye CreditAttribution: coderintherye commented#104: cookie_validate_2946_reroll.patch queued for re-testing.
Kind of just hoping that the requested test is now there. If not maybe I can work on writing one.
Comment #110
Frank Steiner CreditAttribution: Frank Steiner commentedThis is really getting nasty. It's an obvious issue which is seven years old. The patch is few lines of code which everyone can read and understand, but it's been delayed for 2 1/2 years, and now it's blocked again because it needs a simpletest.
I wonder why every other website I know is able to issue a warning when trying to login without cookies, but drupal makes this a huge, unsolvable problem.
Comment #111
JamesK CreditAttribution: JamesK commentedDoes anyone have any examples of Simpletests that check/manipulate the HTTP headers? I'm not really sure where to start with coding this without an example test to base it off of.
Basically we need to test two "browser"s:
- one that ignores any Set-Cookie response header (ignoring Set-Cookie means that a Cookie header is not added to subsequent requests), and
- one that handles Set-Cookie headers normally (Cookie header is added to requests)
Comment #112
coderintherye CreditAttribution: coderintherye commentedWell, drupal_http_request will handle getting/setting the headers for us, I know there are a few tests out there using it. I have one maybe could put up this weekend, but thinking how about we make this something to work on at the core code sprint next week? I'll be there, so I'll be pushing for this issue.
Comment #113
c960657 CreditAttribution: c960657 commentedYou cannot assume that just because $_COOKIE is empty, the browser does not accept cookies. Since #201122: Drupal should support disabling anonymous sessions was fixed in January 2009, we no longer create sessions for anonymous users. If JavaScript is not enabled, the has_js cookie is not set. If JavaScript is disabled in your browser, you cannot log in with this patch.
If $_COOKIE is non-empty, then the browser supports cookies, at least partially. I don't know whether any browser has "partial" support for cookies. I would think (but it's just a guess) that if $_COOKIE is non-empty, we can assume that it will accept our cookie. Comments #57-59 discuss this, but without any clear conclusion AFAICT.
In any case, we need to set a cookie in one request a verify its existance in the next request. Setting a cookie from PHP to all anonymous visitors seems like a bad idea, because a Set-Cookie header is usually a sign that the page should not be cached (e.g. by default (and design) Varnish does not cache pages with a Set-Cookie header).
One possibility is to make the login form return to an interim page that just checks for the existance of the session cookie and then redirects to the final destination. This will add an extra request to all logins. The redirect happens automatically, so the additional request will be invisible to the user (except for a small delay).
If we conclude that a non-empty $_COOKIE is a safe sign that the session cookie will be accepted and the form submission contains a non-empty $_COOKIE (usually containing just the has_js cookie), we can skip the extra round-trip and just redirect to the final destination immediately. This would make the login as fast as today for users with JavaScript enabled, while other with JavaScript disabled would need the extra round-trip.
For inspiration on how to write tests for this, you may want to take a look at modules/simpletest/tests/session.test. To emulate a browser without cookie support you should probably tell cURL to not follow redirects using CURLOPT_FOLLOWLOCATION and then instead follow the redirects “manually” and reset the session cookie between each request.
Comment #114
Owen Barton CreditAttribution: Owen Barton commentedI confirmed that the previous approach does not work with the new lazy session creation.
Here is an alternate approach that avoids adding a redirect simply to detect a cookie. What we do is add a querystring parameter to the destination page the user would end up on. We then check for this parameter and, if the user is not actually logged in, then we know they don't have cookies enabled. We might want to change the user flow a little. For example it may be nicer to do a set_message and redirect to "user", because right now if you log in on /user without cookies you end up on user/123 with the cookies message, but it is an access denied page. This would certainly need a simpletest to check the various combinations of /user vs. block, and with page caching enabled/disabled. First though - what do people think about this approach in general?
Comment #115
Owen Barton CreditAttribution: Owen Barton commentedComment #117
Owen Barton CreditAttribution: Owen Barton commentedStill looking for review on the general approach
Comment #118
catchI think we should consider doing the redirect here. #547570: Login via user login block renders page twice points out that this happens anyway from the login block, and that the redirect is quite expensive - so it adds a dedicated redirect callback to save page rendering. If we used that same redirect callback for user/login then the additional bootstrap would be very cheap, and this would presumably allow us to redirect somewhere useful on failure too.
Comment #119
amc CreditAttribution: amc commentedsubscribing
Comment #120
Owen Barton CreditAttribution: Owen Barton commented@catch - my patch does not actually use (or need) any redirect. I think either approach should work fine - but I am not sure which I prefer...what do you think?
Comment #121
catchEven though the user_init() is just an isset(), I'd be happier with a check just during the process of logging in rather than having that code in the critical path.
Also if we're going to do a redirect from the login block anyway, and have a nice handy callback which controls that, then putting the cookie checking code in there is fairly tidy. The question then is whether the isset() in user_init() and very small bit of code weight there is better or worse than an extra bootstrap (but no page render) on logging in via the form. I'm not sure either way on that but lean slightly towards the log in form.
Comment #122
Owen Barton CreditAttribution: Owen Barton commentedActually, now that I think about it, I am not sure #547570: Login via user login block renders page twice really changes anything that helps us here. The basic workflow is the same as it is now (just we hit a lightweight page, rather than a content page). Specifically in the following, it just changes pageload 2 from building an entire node/123 page, to a simple page - however it is still a single redirect, and we actually need 2 redirects.
Load 1: /node/123 - we can't add a cookie here (without breaking caching) because we don't know if the user will actually use the login block, or just click away
Load 2: user submits login form - we process the login then redirect them on to their destination - we can add a cookie here (and we do already, in fact)
Load 3: user back at node/123 - we can check for a cookie here, but this is basically the same as the patch I have already
If we are going to drop the hook_init isset, then we need to add another redirect either before or after load 2, that has the single purpose of setting or detecting cookies. Given this, I think my approach, or some variant of it is preferable to having 2 redirects on login.
Comment #123
catchI don't like either the double redirect option, or the runtime check on every page here, but neither do I have any better ideas - would be good to get some feedback from others. However some of the information in this issue needs to be added to user_init() in a comment if we go for this option.
Comment #124
c960657 CreditAttribution: c960657 commentedThis is somewhat along what I proposed earlier, but not completely:
Do you think that we can assume that the browser uses the same logic for determining whether to accept or reject a cookie when set using a HTTP header and from JavaScript, assuming that the cookie is set using the same parameters except for the name? In that case we can set a cookie using JavaScript in the onsubmit handler for the login form. The cookie should have the same path+domain+lifetime as the login cookie. When the login form is submitted, we do the extra redirect as already suggested, but only if the cookie set in JS is not present. This allows most users to login without an extra redirect.
Comment #125
MichaelCole CreditAttribution: MichaelCole commentedThe tests are failing, so the patch still needs some work...
Comment #126
David_Rothstein CreditAttribution: David_Rothstein commentedSome of the comments above referred to this being an issue with the installer as well, which is still true. It was reported recently here, and is still an issue in Drupal 7:
#791004: Installer does not warn the user that cookies must be enabled with the correct cookie domain (and fails when they aren't)
Since the installer is something of a separate problem (which the latest patch here doesn't address), it's probably best to keep two separate issues for this, so I am leaving that one open but just cross-linking it here.
Comment #127
webchickSorry. Issues that have been in Drupal since 2003 don't get to hold "critical" status.
Comment #128
webchickComment #129
Frank Steiner CreditAttribution: Frank Steiner commentedIgnoring the problem for 7 years doesn't make it less critical. Getting rejected to login without any notice why it happens is a critical usability issue.
Comment #130
salvisShhh, we're aiming for a world record here...
Comment #131
CZ CreditAttribution: CZ commentedSubscribe.
Comment #132
EvanDonovan CreditAttribution: EvanDonovan commentedSubscribing. Is #114 going to work with lazy session creation, or should we try for #124?
Comment #133
Yar1984 CreditAttribution: Yar1984 commented#114: cookie_validate_2946_114.patch queued for re-testing.
Comment #135
kgeographer CreditAttribution: kgeographer commentedre: cookies and usability
The most recent 6.17 patch update rendered existing Firefox cookies useless. The result is that no recent visitor to my site can log in without first clearing cookies. Unfortunately, they have no way of knowing that. Truthfully, how many would think to do it given no prompt or message to that effect? Attempts to change password fail when following the emailed link. And what is the pain-in-the-a$$ cost for clearing all one's other, perfectly good cookies?
Nice software, generally, though!! Thanks to its authors :^)
Comment #136
salvis@satchinsb: Please don't hijack this issue — create a new one against 6.17.
Comment #137
klonossubscribing...
Comment #138
DanChadwick CreditAttribution: DanChadwick commentedRe: 114, I implemented this technique in a module for my own (not generalized) situation. The only minor issue I found is that if the user logs off and uses the browser's history or back button to return to the page containing the "state=loggedin" query, then the cookie warning message is displayed when it shouldn't be. It would be possible to reword the message to allow for this possibility, absent a better solution.
In reading through the 130+ messages, there seems to be a lack of agreement on the urgency which is hard to explain. Perhaps it is relatively uncommon for Drupal sites to be used by authenticated non-technical users -- the type likely to be frustrated by this. My site has exactly this type of user. I would very much like to see this fixed in D7 and backported to D6. Even if the fix is not absolute perfection, could we get something into core and keep open another issue for research for the next 7 years? ;-)
Please. It's time to plug a serious usability bug for those unlucky enough -- or unskilled enough -- to fall into it ... and for the site owners who then suffer. D7 emphasizes usability after all, no?
Comment #139
dpatte CreditAttribution: dpatte commentedsubscribe
Comment #140
Owen Barton CreditAttribution: Owen Barton commentedComment #141
amc CreditAttribution: amc commented#114: cookie_validate_2946_114.patch queued for re-testing.
Comment #143
dwwIssues like this make we want to stop trying to contribute to Drupal core at all... ;)
- This is at least a major UX bug/WTF. We seem to be totally schizophrenic when it comes to our UI/UX priorities. Half-baked UX solutions are rushed into core under the banner of "UX trumps all" while critical UX bugs like this that actually affect 1000s (millions?) of Drupal users are postponed and punted to low priority. Either creating a "delightful experience" is important or not. If so, we can't downgrade obvious bugs like this to "normal task" just because so many people got burned out trying to get this in and faced various roadblocks.
- I think I'm with catch and I'm leaning towards the double redirect solution. Although it does delay login slightly (in an automated way), a) logging in is a very infrequent operation even on sites that allow authenticated users and b) not all sites even have real authenticated traffic. So, I'd hate to slow down the critical path of user_init() with this check on every page load for every site, just to handle a relatively infrequent thing. Also, it's extremely common on the existing web that when you click the "login" button, you wait a few seconds for at least a few redirects, if not more. It's not like users are going to be shocked or angry if logging in seems complicated and/or slow. And, if the first redirect sends you to a relatively cheap page that just ensures your cookie worked and either prints you the warning message or sends you off to where you wanted to go, it's not going to really be that slow.
Cheers,
-Derek
p.s. Please stop requesting #114 for retesting. The patch will never apply now that #22336: Move all core Drupal files under a /core folder to improve usability and upgrades is done. If we're going that route, we need a re-roll.
Comment #144
coderintherye CreditAttribution: coderintherye commentedSo do we need a completely new patch or do we want to wait for #547570 to land?
As for the concerns about a redirect for authenticated users, as someone who has run a few sites that allow *only* authenticated users, I can say that we had to write our own cookie checks anyways since obviously we wanted those users with cookies disabled to know why they were not able to login. I'd imagine this is pretty true across most sites that require authenticated logins (especially government ones trying to meet 508 guidelines).
So, +1 to the double-redirect, the performance hit should be worth the trade-off.
Comment #145
Owen Barton CreditAttribution: Owen Barton commentedLooking through the session code, it seems that as long as $_SESSION is left empty we should still be able to set other cookies without breaking caching (even reverse proxies with vary-cookie should be OK). If we did this wherever the user form is displayed it seems this might be the most simple option (compared to wiring in an additional redirect). The only downside I can think of is the extra few bytes per-page for all users. We could reduce the latter by using a short cookie name/value. We could even set "has_js" to 0 in php (if it is not yet set), although I think that is more complex since we need to consider the JS interaction.
Note that if we go the double redirect option, it is actually the second redirect (rather than the first) that checks for a cookie. The first redirect would process the login, then redirect to a second page that would check for cookies and direct the user on to their final destination or set a message and send them back (to their original URL, ideally, although we might need to figure in some "origin" querystring parameter for that, I think, since we are no longer in the form processing cycle). Here is the page flow for the double-redirect option.
- Load 1: /node/123 - we can't add a cookie here (without breaking caching) because we don't know if the user will actually use the login block, or just click away
- Load 2: user submits login form - we process the login then redirect them on to a cookie check page - we can add a cookie here (and the login process does already, of course)
- Load 3: user goes to /user/checkcookie?destination=user&origin=node/123, checks for the session cookie and redirects as needed.
- Load 4: user back at node/123 if no cookie, or at user if cookies enabled
Of the 2, I think my preference is for adding a small cookie with login forms, but this is primarily because it feels simpler, rather than performance.
Comment #146
ZenDoodles CreditAttribution: ZenDoodles commentedAdding issue summary tag. Also, I'm not convinced #791004: Installer does not warn the user that cookies must be enabled with the correct cookie domain (and fails when they aren't) isn't a duplicate.
Comment #147
xmacinfo#791004: Installer does not warn the user that cookies must be enabled with the correct cookie domain (and fails when they aren't) is not a duplicate. It deals only with the installer.
We need a warning to regular user (on an already installed Drupal site) that they need to enable cookies to be able to log in on the site.
Right now nothing is displayed if cookies and not enabled and the user have not clues as to why.
Comment #148
xmacinfoAdding Needs tests tag.
Comment #148.0
xmacinfoAdded more information in the issue summary.
Comment #149
Kazanir CreditAttribution: Kazanir commentedI am posting here to echo the others -- how unbelievable is it that Drupal, one of the (allegedly) most mature and complete CMS solutions available, doesn't have a fix for such an obvious, disturbing (and ancient!) UX issue?
Comment #150
xmacinfo@Kazanir: It means that no one was able to write the test required for this patch.
Comment #151
DanChadwick CreditAttribution: DanChadwick commented@xmacinfo - Since this bug is 10 years old and is -- I think we all agree -- quite a serious UX issue, I would propose that we remove the Needs tests flag and re-roll 114 for testing by the community. If it turns out in the future that a better solution than 114 exists, it can always be proposed in new issue.
Comment #152
znurgl CreditAttribution: znurgl commented#7: no-cookie.patch queued for re-testing.
Comment #153
nedjoGiven that this is a common need that's been addressed in many other PHP applications but not in Drupal, we'd do well to look around. What have Joomla and Wordpress done? Anyone who's following this issue able to take on that research and report back?
Comment #154
dwwnedjo raises a good point. Another place to look would be Symfony. ;) Isn't solving stuff like this "for free" part of the promise of having imported so much Symfony code into Drupal core?
Comment #155
salvisIf the missing tests are the problem, then looking around in other projects won't help at all. Technically this is solved, it's a people problem.
Looking in Symfony is certainly a good idea for D8, but it should go into a new issue IMO, because it won't work for D7. This issue here has the code to fix the problem in D7. We could have committed this years ago -- gasp, without tests -- and have it well-tested in the field by now.
I know what our standard procedures are, but in the tenth (!) year of this embarrassing issue, it's pretty obvious that our standard procedures are a hindrance in this case rather than a help. I've come to the conclusion that we lack the will to fix this. Looking around in other projects is just another way to derail this even further. (Not picking on you, nedjo, I know you've worked to bring this forward in the past.)
Comment #155.0
salvisClarified that the patch is too old.
Comment #156
nedjoRecategorizing as a bug, since login is broken without cookies. The priority reflects the fact that the bug presents significant usability issues.
D8 maintainer catch has been responsive in this issue and there's every reason to believe we could get this in for D8, but the patch is not yet ready. I've had a stab at updating the summary with remaining tasks.
Comment #157
David_Rothstein CreditAttribution: David_Rothstein commentedI took a quick look at Wordpress, and it seems to me they do something similar to Owen Barton's first suggestion in #145 (set a cookie when the form is displayed and check it when the form is submitted).
However:
Don't a lot of Varnish configurations strip cookies they don't recognize, and bypass caching entirely if there are any cookies left over? I'm looking, for example, at http://www.lullabot.com/articles/varnish-multiple-web-servers-drupal :
If I understand that correctly, that means people would need to change their Varnish configurations for this approach to work at all, and if they do, suddenly a whole bunch of pages won't be cached anymore. (On the other hand, one could make the argument that if a site wants this behavior, that's something they'll have to live with.)
In terms of Drupal 7 backport, a new cookie would also break things for people using a "blacklist" approach to cookies in Varnish (rather than a whitelist approach) although I suppose those people should already be getting used to things breaking anyway...
Comment #158
David_Rothstein CreditAttribution: David_Rothstein commentedIn any case, here is a test. This was kind of a pain to figure out how to write.
It includes a rerolled version of #114; this should at least serve the purpose of verifying that the test behaves as expected.
Comment #160
David_Rothstein CreditAttribution: David_Rothstein commentedThose two failures look like they're specific to the solution here (probably code that expects a specific URL after logging in and therefore gets confused by the new
?state=loggedin
). So not worth fixing unless this is the actual solution we're going with.Comment #160.0
David_Rothstein CreditAttribution: David_Rothstein commentedAdd issue summary.
Comment #161
nedjo@David_Rothstein: thanks, it's great to have a test in place!
I've updated the summary with details from the Wordpress approach.
In general I lean towards the cookie setting and checking approach. It has the advantage of being outside the critical path, it's explicit (testing to see if we have a logged in user feels hackish), it could be used elsewhere, e.g., at install time, and as Owen suggested it feels simpler than a double redirect.
But, yes, interference with Varnish or other cache solutions is an issue. Currently we set various cookies only in response to user actions (form submissions, logins, etc.), see http://api.drupal.org/api/drupal/modules!user!user.module/function/calls.... But a login form is often presented on all pages of a site.
Looking again to Wordpress, some sys admins explicity skip the wordpress_test_cookie in Varnish config, see http://kaanon.com/blog/work/making-wordpress-shine-varnish-caching-syste.... Presumably we'd see the same with Drupal, meaning that this fix would be missing from Varnish-served sites.
Comment #162
pplantinga CreditAttribution: pplantinga commentedRe-roll. I support this approach.
Comment #163
nedjoThanks for rerolling. hook_init() is gone, https://drupal.org/node/2013014, so the patch would need to use a different approach.
Comment #164
pplantinga CreditAttribution: pplantinga commentedFair enough.
How's this for proof-of-concept? I kind of hijacked the MaintenenceModeSubscriber, so we'd probably have to move the code to its own Subscriber or rename that subscriber, but at least it seems to fix the issue for me. Test might need to be tweaked though.
Comment #166
pplantinga CreditAttribution: pplantinga commentedComment #167
xmacinfoCannot be reviewed until the patch is rerolled.
Comment #168
pplantinga CreditAttribution: pplantinga commentedI set it to needs review because I needed input about whether the method was a valid one. It gives the correct result in manual testing (though the test needs to be tweaked, which I couldn't figure out either).
Comment #168.0
pplantinga CreditAttribution: pplantinga commentedUpdate summary with test info and example from Wordpress.
Comment #169
jessebeach CreditAttribution: jessebeach commentedAfter 11 years of surviving with the bug in place, I think we can safely downgrade this to Normal.
Comment #170
jessebeach CreditAttribution: jessebeach commentedI was convinced in chat to put this back to Major.
Comment #171
effulgentsia CreditAttribution: effulgentsia commentedFor context, the reasoning I gave for this being Major is similar to #143. https://drupal.org/node/45111 defines major bugs as ones that have significant repercussions as opposed to normal bugs that are isolated to one piece of functionality. Since the inability to log in affects the use of the entire software, that makes this major by that definition. However, it's not critical, since it affects a tiny percentage of users and has a workaround (enable cookies).
Comment #172
jhedstromThe patch here has tests, removing tag.
Comment #173
jcnventura CreditAttribution: jcnventura at Wunder commentedRe-rolling the patch, let's waste some test bots time.
And for those wandering.. Yes, this is a 12-year old major bug, first detected in Drupal 4.2 or 4.3 (not sure exactly...).
Comment #174
jcnventura CreditAttribution: jcnventura at Wunder commentedTest bots are go!
Comment #177
jcnventura CreditAttribution: jcnventura at Wunder commentedComment #181
iMiksuTaking a look on the failures.
Comment #182
iMiksuThere are two methods (
\Drupal\system\Tests\Session\SessionHttpsTest::loginHttp()
and\Drupal\system\Tests\Session\SessionHttpsTest::loginHttps()
) which needed some improvements to support recently added?state=loggedin
query suffix to the login process from comment #177.I changed them by passing query parameters separately to
\Drupal\simpletest\WebTestBase::drupalGet()
call:Comment #183
catchSince this adds new public functions and interface text, moving to 8.1.x.
Patch also needs updating for $GLOBALS['user'] removal.
Comment #185
anoopjohn CreditAttribution: anoopjohn at Zyxware Technologies commentedRemoved global $user and rerolled the patch. Made some minor coder corrections as well.
Comment #187
ifrikComment #188
jcnventura CreditAttribution: jcnventura at Wunder commentedSorry BigPipeTest.php, but you can't test for no redirects in a page where we actually redirect on purpose.
Comment #189
jcnventura CreditAttribution: jcnventura at Wunder commentedComment #191
ifrikLooks like the test needs fixing then.
Comment #192
Wim LeersThis analysis is not correct I'm afraid.
This patch is making changes that causes certain defaults/expectations to change. So, yes,
BigPipeTest
needs a very minor change: it needs to now expect that?state=loggedin
query argument. Fixed that.(Also reverted the change in #188, that was the wrong change.)
But, more importantly, this patch uncovers a bug in the
redirect.destination
service. Because BigPipe calls this:… but it returns
/user/1
, whereas it should return/user/1?state=loggedin
.Fortunately a simple fix! :)
This will also need to update
\Drupal\Tests\Core\Routing\RedirectDestinationTest
, because that unit test clearly is not yet testing this. Hence .Comment #193
Wim LeersAnd since I touched this patch now anyway, here's a review:
This should not use
$_GET
. It should use$event->getRequest()->query->get('state') === 'loggedin'
.This should also use the Request object.
Should use
Url::fromRoute()
.Comment #195
Wim LeersFailures in
RedirectDestinationTest
… so that was testing this stuff, but with the wrong expectations!Comment #196
jcnventura CreditAttribution: jcnventura at Wunder commentedThis patch addresses the problems identified by Wim in his review (#193).
It does not fix the failing tests, but I'm setting it to review to make sure I didn't break other tests.
Comment #197
Wim Leers#196's interdiff looks great! Next: fixing
RedirectDestinationTest
, and potentially adding missing test coverage there :)Comment #200
xjm@webchick, @catch, @Cottser, @effuglentsia, and I agreed that this is a major issue because it interferes with normal visitors' use of the site in a way they cannot troubleshoot without a meaningful error message.
We decided this is a bug in the User module, even if we make additions to lower subsystems to support the fix.
Comment #201
vijaycs85Fixing test fails...
Comment #202
deepakrmklm CreditAttribution: deepakrmklm at Zyxware Technologies commentedPassing query parameters separately to \Drupal\simpletest\WebTestBase::drupalGet() call is fine.
Comment #207
ifrikComment #208
xmacinfoPlease leave at Needs work, as any patch existing in this issue needs an update or a reroll.
Comment #209
ifrikSorry, I hadn't actually meant to change this issue at all.
Comment #210
Gogowitsch CreditAttribution: Gogowitsch at QuoData GmbH Quality & Statistics for ÖQUASTA commentedI can confirm this works.
I've updated the patch from #202 so it applies cleanly to the 8.6.x-dev branch.
Comment #212
xmacinfoIn the past, this issue failed to be pushed to core because tests were missing.
@Gogowitsch were you able to run the tests too?
Comment #213
Gogowitsch CreditAttribution: Gogowitsch at QuoData GmbH Quality & Statistics for ÖQUASTA commented@xmacinfo unfortunately no. I kept fighting various issues and have given up after 8 hours. I keep getting many more than the 2 failed
big_pipe
tests. I've looked at the BigPipeTest.php, but cannot match the output to the 8.6.x-dev branch. I'm fine adding tests to the patch myself, but would need an environment first that lets me reproduce what drupal.org's CI sees.Can you point me to the right resources? I'm currently using an old custom vagrant machine for running Drupal tests.
Comment #214
Frank Steiner CreditAttribution: Frank Steiner commentedThis issue hasn't been resolved for 15 years now? That's simply laughable. Really a deterrent example for everyone who's thinking about writing a patch for Drupal.
Comment #215
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedWhy is that comment making me sad? It is like some other comments on this issue. It is an anti-contribution. It is demotivating.
How about motivating instead? Organizations that are feeling pain from this issue for so long and want to get this done could do so in a number of ways:
Comment #217
wengerkHere is the reroll of #210 with the
Drupal\Tests\big_pipe\Functional\BigPipeTest::testNoJsDetection()
fix.What can we do to go forward with this issue ?
I also remove the whole
user_login_form_submit
as all the code was already done by\Drupal\user\Form\UserLoginForm::submitForm()
, am I wrong ? What was the purpose of this hook, the comment wasn't very usefull of Why it was here ^^ ? By removing it no tests fails, so what was the real purpose of this hook, something uncovered ?Comment #218
xmacinfoAs per previous patch by @wengerk.
Comment #219
xmacinfoThe tests are passing. Congratulations!
The next step is to find someone to review the code (and possibly test your patch against 8.7.x-dev on their computer).
@wengerk : we generally need only one user to validate the patch and change the issue to RTBC. I am not setup yet to do this.
Comment #220
tstoecklerComment #221
nedjo@wengerk
Thanks for the new patch.
Another step could be to update the issue summary (and then remove the "Needs issue summary update" tag). Relevant documentation is here.
Comment #222
wengerkThanks for your help @xmacinfo & @nedjo !
I was more wondering about a code review & code approach. Here are some suggestions of code that could be changed :
Drupal\Core\EventSubscriber\MaintenanceModeSubscriber::checkUserCookies
should be moved to a better appropriate ServiceSubscriber such as:Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber
. For now, the checkUserCookies has nothing in relation with the MaintenanceMode.@see user_login_form_submit().
should be@see \Drupal\user\Form\UserLoginForm::submitForm()
$_GET
should be avoided. We should use the Symfony Request Object. So this implementation$_GET['state']
should be$event->getRequest()->query->get('state');
.$_SERVER
should be avoided. We should use the Symfony Request Object. So this implementation$_SERVER['HTTP_HOST']
should be$event->getRequest()->server->get('HTTP_HOST');
.$events[KernelEvents::REQUEST][] = ['checkUserCookies'];
should follow the naming convention & be renamed asonRequestlCheckUserCookies
oronKernelCheckUserCookies
$this->account->isAnonymous()
instead of!$this->account->isAuthenticated()
.\Drupal::url
should beUrl::fromRoute()
.We should not use
%3Fstate%3Dloggedin
but&state=loggedin
. We need to alter the tests a little bit withUrlHelper::encodePath
to make it readable.What do you think ?
PS: Oppsy I didn't see the message #193 of Wim Leers where he already spotted some of those changes ! So I think we should change them before requesting a review.
Comment #223
xmacinfo@wengerk Of course, you can apply all the enhancements you and Wim Leers spotted.
Your changes, along with the explanations you provided will make it easier to review the patch and increase the chance of the patch to be accepted by the core maintainer.
Comment #224
wengerkSo after reading & making a diff of the latest patches from this issue, it seems something went wrong on #202.
The patch #201 was pretty good, but the patch #202 remove some improvement of #201 without nobody notices it. Then we rerolled the #202 instead of #201 and it snowball until my own patch on #217.
Here is a patch from #217 which include (I hope so) all the necessary changes from #201 & #222.
So here a list of changes we still have to work on it, some are suggestions & others are actions to do before merging:
Drupal\Core\EventSubscriber\MaintenanceModeSubscriber::checkUserCookies
should be moved to a better appropriate ServiceSubscriber such as:Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber
. For now, the checkUserCookies has nothing in relation with the MaintenanceMode.user_login_form_submit
hook. What was the purpose should we keep it ?Comment #225
wengerkComment #226
AaronBaumanUpdated issue summary and rerolled to reflect #217 tasks.
Changes in this patch from #217:
UrlGeneratorTrait was not used. Removed.
To address some of the remaining tasks / outstanding questions:
user_login_form_submit
appears to have been cruft, possibly something inadvertantly added from D7? We're good to remove it.UserBlocksTest
,SessionHttpsTest.php
, andBigPipeTest
have been updated to reflect the changes in this patch.Does this need additional test coverage?
If so, can someone suggest a testing strategy?
If not, please remove the "Needs tests" tag, and this is ready for RTBC
If the user doesn't have cookies enabled, they won't get logged in.
If they use the back button it will still be relevant.
If the user does enable cookies and successfully logs in, then uses the back button to go all the way back... seems like that's a pretty far edge case that we don't really need to worry about. Core doesn't use special handling anywhere else to deal with oddities that may arise from the back button, and I don't think we should start now.
Comment #228
AaronBaumanmissed an "s"
Comment #229
xmacinfoAs previous comment, removing the “needs tests” tag.
I am not setup to test this patch, so leaving the Status to “Needs review”.
Comment #231
tatarbjlet's see how does the code behave on 8.8.x, retest is sent.
Comment #232
tatarbjRerolled patch on 8.8.x
Comment #233
tatarbjfixing the coding standard issues from #232
Comment #237
larowlanComment #238
mxr576Comment #239
wengerkHere a rerolled patch for working on
9.1.x
&9.2.x
.During the reroll, I address the usage of deprecated
Symfony\Component\HttpKernel\Event\GetResponseEvent
to useSymfony\Component\HttpKernel\Event\ResponseEvent
onDrupal\Core\EventSubscriber\AnonymousUserResponseSubscriber
This patch reroll does not apply to
8.9.x
and9.0.x
, we need to create another specific patch if we want to merge on8.9.x
,9.0.x
,9.1.x
&9.2.x
.Since it target
9.2.x-dev
I did not create those reroll (8.9.x
,9.0.x
).PS: I was not able to create
interdiff
between 233 and 239. it crash with "Error applying patch1 to reconstructed file". Sorry people.Comment #240
ifrikWorking on this during contrib day today.
Comment #241
michaellenahan CreditAttribution: michaellenahan at Hubert Burda Media commentedAfter applying #239 patch on 9.2.0-dev in a browser with cookies completely disabled, I get this error after login.
https://sprint-20201209-1650.ddev.site:8443/en/user/login
TypeError: Argument 1 passed to Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber::onKernelCheckUserCookies() must be an instance of Symfony\Component\HttpKernel\Event\ResponseEvent, instance of Symfony\Component\HttpKernel\Event\RequestEvent given in Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber->onKernelCheckUserCookies() (line 90 of core/lib/Drupal/Core/EventSubscriber/AnonymousUserResponseSubscriber.php).
Here is the backtrace:
Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber->onKernelCheckUserCookies(Object, 'kernel.request', Object)
call_user_func(Array, Object, 'kernel.request', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.request') (Line: 134)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 2) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 2, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 2, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 2, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 2, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 2, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 2, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 2, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 2) (Line: 166)
Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber->makeSubrequest(Object, '/system/403', 403) (Line: 112)
Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber->on403(Object) (Line: 109)
Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase->onException(Object, 'kernel.exception', Object)
call_user_func(Array, Object, 'kernel.exception', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.exception') (Line: 219)
Symfony\Component\HttpKernel\HttpKernel->handleThrowable(Object, Object, 1) (Line: 91)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 706)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Comment #242
ifrikThe same error also occurs _with_ cookies enabled, and for users who are already logged in.
Comment #243
ifrikInterdiff
Comment #244
wizonesolutionsI "mentored" @michaellenahan on fixing the error in this patch. Someone else will likely explain more, but the issue was that the reroll by @wengerk refactored
GetResponseEvent
toResponseEvent
, but the kernel actually passes aRequestEvent
toKernelEvents::REQUEST
listeners now. We were on screen share and saw the changes work after fixing that.Comment #245
michaellenahan CreditAttribution: michaellenahan at Hubert Burda Media commentedGetting great mentoring from wizonesolutions, ifrik and jcnventura today at Drupalcon Europe.
I made the changes as suggested by wizonesolutions, see this interdiff:
https://www.drupal.org/files/issues/2020-12-11/interdiff_239-245.diff
New patch attached:
https://www.drupal.org/files/issues/2020-12-11/2946-245.patch
With the patch applied, I confirm that, with cookies disabled, when I log in, I get the error message as shown in this screenshot:
Comment #246
michaellenahan CreditAttribution: michaellenahan at Hubert Burda Media commentedComment #247
ifrikThe patch works. If a user doesn't have cookies enabled, then they see not only "Access denied" when they try to log in, but also a message that states that they need to enable cookies to login.
Screenshot:
https://www.drupal.org/files/issues/2020-12-11/Screenshot.png
Comment #248
xmacinfoOh nice! That's an 18 year old bug! Thank you so much for all your work!
Comment #249
xmacinfoComment #251
alexpottThanks for working on this. Nice to see activity on such a low NID :)
I think the name
state
is very very generic. It also implies that we're going to always track this state via the query which is not correct. I think adding a more indicative query string that is way less likely to clash with anything existing is a good idea. For examplecheck_logged_in=1
would indicate more of what is going on thanstate
.A cursory search of contrib shows this concern is real - http://codcontrib.hank.vps-private.net/search?text=query-%3Eget%28%27sta...
The $request->server->get('HTTP_HOST') can give the wrong answer. For example when you are using host forwarding. This should be $request->getHost()
This message is never tested. We can test by performing a request with the query string as the anonymous user.
Adding this to a class called AnonymousUserResponseSubscriber feels tricky because it about responses but this is about requests. The description for the class is
* Response subscriber to handle finished responses for the anonymous user.
. This change makes that not true.Fortunately I think there is a much place to put this. I think we can add this to
\Drupal\user\Authentication\Provider\Cookie::applies()
we can change the code there to make it do:I've tested this locally and it seems to work just great.
user_init() does not exist. This should @see to the event subscriber. The @see should be in the method docs because they actually works with IDEs and api.drupal.org better.
This does not check parameter. See #3164686: WebAssert::addressEquals() and AssertLegacyTrait::assertUrl() fail to check the querystring
Comment #252
michaellenahan CreditAttribution: michaellenahan at Hubert Burda Media commentedThanks for the review, I was not sure about points 5 and 6, but implemented the other points.
1. Querystring changed to ?check_logged_in=1
2. $request->getHost() ... done
3. Was not sure where to put the test, I put it in testUserLoginBlock() for now, even though it is not actually testing the login, but it is closely related to that.
4. Added code to \Drupal\user\Authentication\Provider\Cookie::applies() as suggested
5. Not sure what you meant by "This should @see to the event subscriber" ... so this is still to-do.
6. Also not sure what to do here ... so also still to-do.
Comment #254
xmacinfoComment #255
alexpottThe patch attached tweaks the approach of where the query parameter is added and what causes it.
user_login_finalize()
sets something in session to tell the system we need to check that cookie login is going to work. Then in the same request the Cookie auth provider listens to responses and checks if a redirect is going to happen and adds the request param as necessary to the redirect url. This change means that all usages ofuser_login_finalize()
will do the is cookie working check so log ins via the one time form will also be checked for this (and any contrib that usesuser_login_finalize()
too ftw).Also I've added a proper test where cookies are disabled in the guzzle client that makes requests during tests.
I make the patch rather than doing review comments because I couldn't work out how to explain how to do this without actually doing it. And once i did that not posting a patch seemed silly.
Comment #256
michaellenahan CreditAttribution: michaellenahan at Hubert Burda Media commentedAbsolutely. Thanks!
I tested the patch in a browser with cookies disabled.
Works as expected for a log in via user/login.
Works as expected for the one-time login.
Screenshots attached.
Leaving at Needs Review, I don't have enough knowledge to mark RTBC. But I learned a lot from reading your patch and your comment :)
https://www.drupal.org/docs/develop/issues/fields-and-other-parts-of-an-...
Comment #257
michaellenahan CreditAttribution: michaellenahan at Hubert Burda Media commentedComment #258
xmacinfoI queued a test run on PHP 8. Let's see green!
So far, based on the latest comments and code change by @alexpott, I mark this as RTBC.
Comment #259
ifrikI've just tested it as well, and the error message shows up as expected.
Comment #260
ifrikComment #261
ifrikNow how does this work with merge-requests?
I've made one which has patch #245 in it, but obviously that shouldn't be merged now. But I can't cancel that one, and I can't add a new merge request with a new patch.
Comment #262
larowlannow we're using this 3 times, should we use a local variable? Micro-optimisation but each call to \Drupal::service() adds some overhead
pity that these methods aren't chainable
Comment #264
raman.b CreditAttribution: raman.b at OpenSense Labs commentedNice catch. Let's do that before this goes in
Comment #265
alexpottWe need to trigger a constructor deprecation here... there's things on contrib that depend on the constructor...
See http://codcontrib.hank.vps-private.net/node/30896787 for example.
Comment #267
xmacinfoComment #268
LendudeOther then the warning, we also need the parameter to be NULL by default and we need to fill it from \Drupal:: when it is NULL, I think that is still missing
See
\Drupal\book\Form\BookAdminEditForm::__construct
Comment #269
quietone CreditAttribution: quietone as a volunteer commentedThat is odd, I thought I had put that in. Fixed now.
Comment #270
sokru CreditAttribution: sokru as a volunteer commentedTested manually, looks good. Updated issue summary with current behavior on Drupal 9.2.x.
Comment #271
nod_I know this is a very old issue, but when I read the issue summary and see the solution I'm wondering if a JS solution is not a better approach as far as UX is concerned, since this issue was mainly about the user experience of the login with cookies disabled.
We can detect the fact that a browser can store cookies or not with
navigator.cookieEnabled
and add a warning right on the form before the user submits it, or we could even prevent the form from being submitted. This would be a solution with what I would say is a better UX, that takes care of most users, then we would need to decide what to do for people with no JS and no cookies, is it worth adding this code for that amount of users?(also it's interesting to see that 15 years later, we can find the same piece of code at the same URL for wordpress :)
Comment #272
alexpott@nod_ it's possible there might be other auth providers that work without cookies. Having the check part of auth provider means that the logic is in the correct place. Also other forms of authentication can use the same method to check.
Also it means JS on every page of a site with a login block / form somewhere for anonymous users - atm without big_pipe installed there's no JS when installing standard... not true though if you change the theme to olivero...
Comment #273
larowlanIt looks like we're only touching Cookie in the current patch and the issue summary is specifically about cookies.
Comment #274
quietone CreditAttribution: quietone as a volunteer commentedNeeds work for the unresolved comment.
Comment #275
alexpott@larowlan the bit other auth providers can use is
in user_login_finalise() - then they can use the session
check_logged_in
to ensure login as worked too.Comment #276
quietone CreditAttribution: quietone as a volunteer commentedThat fixes the point raised by larowlan.
Comment #277
dwwFeedback addressed, back to RTBC! Wonderful to see this finally getting fixed. Thanks to everyone who works on this over all the years. Huzzah!
Comment #279
quietone CreditAttribution: quietone as a volunteer commentedI notice that the MR has not been tested since 24 March. Therefor I am making a patch and uploading it so that testing will happen every two days.
Comment #281
quietone CreditAttribution: quietone as a volunteer commentedFailed on Field_ui.Drupal\Tests\field_ui\FunctionalJavascript\ManageDisplayTest, which is not listed in #2829040: [meta] Known intermittent, random, and environment-specific test failures.
However, since I've never been able to run FunctionalJavascript tests locally, starting a retest.
Comment #282
quietone CreditAttribution: quietone as a volunteer commentedBack to RTBC
Comment #284
quietone CreditAttribution: quietone as a volunteer commentedFailed in Field_layout.Drupal\Tests\field_layout\FunctionalJavascript\FieldLayoutTest, #3099427: [random test failure] FieldLayoutTest::testEntityView(). retesting
Comment #285
quietone CreditAttribution: quietone as a volunteer commentedTests passing back to RTBC
Comment #286
smustgrave CreditAttribution: smustgrave at Mobomo commentedQuestion. I just updated my local to 9.2.0 and appear to be getting an issue with logging in. Could this be why?
Comment #287
stopopol CreditAttribution: stopopol commentedI have the same issue after updating core to 9.2.0. Downgrading to 9.1.10 solves the issue.
Comment #288
alexpott@stopopol @smustgrave check out https://www.drupal.org/project/redirect_after_login/issues/3214949
Comment #289
phenaproximaAdding credit for comments 200 to 289.
Comment #290
pameeela CreditAttribution: pameeela commentedAdded credits for comments 1-200.
Comment #291
pameeela CreditAttribution: pameeela commentedOne more credit.
Comment #293
larowlanManually tested this one more time.
Took me forever to work out how to even turn off cookies, its so rare to do so nowadays.
Works as it says on the box
🎉🐛🔨
To everyone involved in smashing this 4 digit nid core bug, thank you
Comment #294
xmacinfoAmazing work everyone! Infinite thank you!
Comment #295
jcnventura CreditAttribution: jcnventura commentedSo happy this was committed. Just for historical context.. This was reported as a Critical bug for Drupal 4.2.0, 17.5 years ago. I first worked on this (#173) in one of the code sprints for Barcelona 2015. I was hoping we could have gotten this into Drupal core 8.0.0. And now, it will be in 9.3.0. When it gets released on that stable version next December, over 18 years will have passed.
So again, congratulations to all those who came before and after me to get this done. You all rock!!
Comment #297
klonosThis applies to 7.x, yet I see no "needs backport" tag. Was a separate issue filed for D7 and I missed it somehow?
Comment #298
xmacinfo@klonos: You need to create a new ticket for Drupal 7. There is probably an old patch above that would still apply for Drupal 7, minus tests.
Comment #299
izmeez CreditAttribution: izmeez commentedFor D7 the patch in comment #76 #2946-76: Login fails and no warning is issued if cookies are not enabled appears to be the last one that worked but the issue of adding tests delayed it indefinitely. Also remember the related issue #791004: Installer does not warn the user that cookies must be enabled with the correct cookie domain (and fails when they aren't). A new issue for the D7 backport, if there is to be one, makes sense.
Comment #300
cosolom CreditAttribution: cosolom commentedI'm not sure that all works fine, because after logged out I get this message
And url have attached /?check_logged_in=1
Comment #301
izmeez CreditAttribution: izmeez commentedNew issue created for D7 backport #3255713: [D7] Login fails and no warning is issued if cookies are not enabled with reference to patch in comment #76. That patch should probably be attached to the new issue for review.
Comment #302
Back From 7 CreditAttribution: Back From 7 commentedThis is why I despise Drupal. Very complicated, bloated and not reliable...
Comment #303
richard.e.morton CreditAttribution: richard.e.morton as a volunteer commentedI appreciate all the hard work. But I'm sure everyone will agree that this is a hilarious timescale for this to be resolved. Just consider what has happened in the intervening (nearly) two decades...
Reporter: anders
Created: 20 Sep 2003 at 06:30 UTC
Updated: 6 Apr 2022 at 21:11 UTC
Comment #304
Eduardo Morales AlbertiI added redirection to the user login with a "hash" and I saw that the URL loses the URL fragment because the URL parser has the property fragment without hash but the Cookie class tries to access the property with hash.
On the method Cookie::addCheckToUrl() the option fragment is considered with hash, but on the UrlHelper is without Hash, so the response loses the fragment.
https://git.drupalcode.org/project/drupal/-/commit/d5ee37a05d0e43a93d280...
UrHelper::parse()
https://git.drupalcode.org/project/drupal/-/blob/d5ee37a05d0e43a93d28050...
I opened a new issue for this https://www.drupal.org/project/drupal/issues/3278692#comment-14504031 and a MR https://git.drupalcode.org/project/drupal/-/merge_requests/2221/diffs
Comment #305
patchak CreditAttribution: patchak commentedHi all, I have this exact same bug, it seems it's still in Drupal 10, I have been having issues regarding login and I now think this is because cookie are not set properly on the browser (as I never say any request for accepting cookies) and the login on new installs keeps failing.
I'm running on cloud ways PHP server, happy to provide more details...
thanks
Comment #306
xmacinfoPlease open a new ticket and relate this ticket to the new one.