Currently, when using BrowserTestBase and FunctionalJavascriptTestBase, when you log in user and stay on the same page or go to other pages using clickLink, the user session expires after 30 seconds, mostly resulting in 403 pages and thus failing tests.

Cases in point:
#2754985: [backport] Add JavaScript test coverage for adding an exposed filter in Views UI
#2771187: Add javascript testing for pagination on AJAX enabled views

This might have something to do with my local environment setup, but since I get exactly the same errors when uploading these tests to d.o I think it's something in the base setup.

I'll add a test-test here that basically clicks on the same link 15 times in a row. There is no reason this shouldn't work, but it stops working after about the 6th click (and on inspection will show a 403 page). If you re-login after every 4 clicks, the 15 clicks get done in the end.
The test is in BrowserTestBase but the same happens for FunctionalJavascriptTests as can be seen in the related issues.

The problem is the timestamp in the SIMPLETEST_USER_AGENT cookie that only allows requests within 5 seconds of it being set.

In WTB/BTB this is not an issue because every HTTP request goes through drupalGet() etc., so it will get the always up to date header, no matter what happens in between. In JTB we though no longer control the request, which results in using the cookie from the last drupalGet() which might be quite old.

CommentFileSizeAuthor
#64 test-session-expire-2771547-64.patch2.7 KBLendude
#64 interdiff-2771547-61-64.txt389 bytesLendude
#61 test-session-expire-2771547-61.patch2.67 KBLendude
#61 interdiff-2771547-59-61.txt839 bytesLendude
#59 test-session-expire-2771547-59.patch2.59 KBLendude
#59 interdiff-2771547-52-59.txt1.88 KBLendude
#52 interdiff.txt913 bytesklausi
#52 test-session-expire-2771547-52.patch2.42 KBklausi
#47 interdiff.txt2.75 KBklausi
#47 test-session-expire-2771547-47.patch2.56 KBklausi
#33 test_session_expire-2771547-33.patch4.03 KBLendude
#33 interdiff-2771547-31-33.txt523 bytesLendude
#31 interdiff.txt2.47 KBklausi
#31 test_session_expire-2771547-31.patch4.08 KBklausi
#26 test_session_expire-2771547-26.patch3.59 KBLendude
#26 interdiff-2771547-13-26.txt1.88 KBLendude
#13 test_session_expire-2771547-13.patch2.12 KBLendude
#13 interdiff-2771547-10-13.txt542 bytesLendude
#10 test_session_expire-2771547-10.patch2.11 KBLendude
#7 test_session_expire-2771547-7.patch2.44 KBLendude
#7 interdiff-2771547-2-7.txt1.74 KBLendude
#2 test_session_expire-2771547-2.patch2.06 KBLendude
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Lendude created an issue. See original summary.

Lendude’s picture

Status: Active » Needs review
FileSize
2.06 KB

The test-test, this is not up to any standard (don't bother reviewing it), just using it as an example.

Status: Needs review » Needs work

The last submitted patch, 2: test_session_expire-2771547-2.patch, failed testing.

dawehner’s picture

I had some issues with some CURL timeouts before which has been 30 seconds on my local system for some reason. I never had the time to actually debug it, so I'm not sure what could have caused that ... This issue is totally worth to do!

Lendude’s picture

Just adding some steps I tried to find what's going on.

When setting debug mode in phantomJS I see:

2016-07-24T20:30:20 [DEBUG] HTTP Request - Content Body: {"name":"set_cookie","args":[{"name":"SIMPLETEST_USER_AGENT","value":"simpletest506806%3A1469385020%3A5795093cdf8a49.26579193%3Au6JP9I9J-ekNIbFwc9fmbrC4Js3xmlWzzB1DFMkEDeo","domain":"test.d8.dev"}]}
REQUEST: {"name":"set_cookie","args":[{"name":"SIMPLETEST_USER_AGENT","value":"simpletest506806%3A1469385020%3A5795093cdf8a49.26579193%3Au6JP9I9J-ekNIbFwc9fmbrC4Js3xmlWzzB1DFMkEDeo","domain":"test.d8.dev"}]}

2016-07-24T20:30:20 [DEBUG] CookieJar - Saved "SESSc26c245048d818938357cc6dbb3fae47=-W9aVZjUX2lNxsq9nUHTX_rqbNxJnxGcOGIPBXDOR3U; HttpOnly; expires=Tue, 16-Aug-2016 22:03:39 GMT; domain=.test.d8.dev; path=/"
2016-07-24T20:30:20 [DEBUG] CookieJar - Saved "SIMPLETEST_USER_AGENT=simpletest506806%3A1469385020%3A5795093cdf8a49.26579193%3Au6JP9I9J-ekNIbFwc9fmbrC4Js3xmlWzzB1DFMkEDeo; domain=.test.d8.dev; path=/"
2016-07-24T20:30:20 [DEBUG] CookieJar - Rejected Cookie "SIMPLETEST_USER_AGENT=simpletest506806%3A1469385020%3A5795093cdf8a49.26579193%3Au6JP9I9J-ekNIbFwc9fmbrC4Js3xmlWzzB1DFMkEDeo; domain=test.d8.dev"
RESPONSE: {
    "response": false
}

So something weird is happening with the setting of the SIMPLETEST_USER_AGENT cookie. But when stepping through this with xdebug that cookie is set, so that doesn't appear to be the problem. Also, drupal_valid_test_ua() always seems to pass while stepping through, so that doesn't appear to be the source of the 403.

dawehner’s picture

What does 2016-07-24T20:30:20 [DEBUG] CookieJar - Rejected Cookie actually means?

Lendude’s picture

Title: In Browser and FunctionalJavascript tests the user session expires after about 30 seconds. » In Browser and FunctionalJavascript tests SIMPLETEST_USER_AGENT cookie expires after about 30 seconds.
Status: Needs work » Needs review
FileSize
1.74 KB
2.44 KB

The documentation is somewhat sparse on that:

addCookie
addCookie(Cookie) {boolean}
Introduced: PhantomJS 1.7
Add a Cookie to the page. If the domain does not match the current page, the Cookie will be ignored/rejected. Returns true if successfully added, otherwise false.

Ok, but found that the issue indeed appears to be in that SIMPLETEST_USER_AGENT cookie.

Calling prepareRequest() before each AJAX request triggering action, seems to work as a workaround/fix.

The underlying problem seems to be that the cookie gets set in prepareRequest() without an expiration time and that the current interface for the driver setCookie method only supports name/value ($this->driver->setCookie($name, $value);), so that sort of eliminates the possibility of just adding a longer expiration time.

Not sure what the right way to go is here.

Lendude’s picture

+++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Session/SessionTest.php
@@ -29,12 +31,17 @@
+    /** @var Role $role */
+    $role = Role::load('anonymous');
+    foreach ($permissions as $perm) {
+      $role->grantPermission($perm);
+    }
+    $role->save();

This is the remnant of me trying to add the right permissions to the anon role to work around the session cookie expiring. This didn't help.

Status: Needs review » Needs work

The last submitted patch, 7: test_session_expire-2771547-7.patch, failed testing.

Lendude’s picture

Title: In Browser and FunctionalJavascript tests SIMPLETEST_USER_AGENT cookie expires after about 30 seconds. » In Browser and FunctionalJavascript tests SIMPLETEST_USER_AGENT cookie needs to be set every 5 seconds
Issue summary: View changes
Status: Needs work » Needs review
FileSize
2.11 KB

Got it.

The problem is that the SIMPLETEST_USER_AGENT cookie contains a timestamp and only requests done within 5 seconds of the cookie being set are deemed valid. This means that the cookie needs to be set before each request. This probably works fine when you only have a limited number of ways to trigger a request (drupalGet, drupalPostForm), but becomes hard when there are X number of ways to do this through Mink.

This patch sets the timeout to 180 seconds. I'm assuming this has some sort of security implications since the whole reason for SIMPLETEST_USER_AGENT seems to be security related, so I'm not saying this is the right fix, it just points out the root of the problem.

If this needs to stay at 5 seconds then the only option I see to work with this is calling prepareRequest() before each action that would trigger a request, which seems annoying.

Status: Needs review » Needs work

The last submitted patch, 10: test_session_expire-2771547-10.patch, failed testing.

Lendude’s picture

Annoying, this passes locally......

Lendude’s picture

Status: Needs work » Needs review
FileSize
542 bytes
2.12 KB

Grumble, stupid namespace error...

The last submitted patch, 10: test_session_expire-2771547-10.patch, failed testing.

dawehner’s picture

Issue summary: View changes

@Lendude
This makes sense.

Here is an update of the issue summary.

I also asked @chx to clarify why we need this time validation in the first place.

dawehner’s picture

According to chx this is some way of protection against replay attacks.

Lendude’s picture

Issue tags: +JavaScriptTest

@dawehner thanks for the summary update, that really sums it up nicely!

Hmm most APIs I've used had like 5-15 minute windows on their anti-replay timestamps, so would it be ok to raise it here too? I have no idea.

I just don't see any option other then either raising the window or calling prepareRequest() a lot. Neither seems great, but this is currently blocking any javascript test running operations for longer then 5 seconds on a page. The only reason I think this is not a bigger deal yet (as in priority more then normal) is because we don't have a lot of javascript tests yet.

slashrsm’s picture

This patch solves a lot of problems that we have in Entity browser: #2765789: [Test] Create basic Javascript test base. Solving this is critical for test coverage improvements of Entity browser.

dawehner’s picture

Issue tags: +Needs security review
Hmm most APIs I've used had like 5-15 minute windows on their anti-replay timestamps, so would it be ok to raise it here too? I have no idea.

Yeah. 5-15 minutes still sounds sane. I still believe that you should simply not consider to even install simpletest module, in which case we exit early.

Let's see whether the security team could help us out here. Feel free to ping me at any point.

alexpott’s picture

Could this explain the random fails for postgres in #2737805: Convert web tests to browser tests for forum module?

Lendude’s picture

@alexpott I could easily see this leading to random fails if you have tests that run around 5 seconds, some runs will take longer, some shorter, this will totally look like random fails.

Had this happen during all the debugging I did where a test would suddenly pass out of nowhere, and then revert back to failing again.

Time to bump this to major yet?

klausi’s picture

Status: Needs review » Needs work
+++ b/core/includes/bootstrap.inc
@@ -642,7 +642,7 @@ function drupal_valid_test_ua($new_prefix = NULL) {
     // Since we are making a local request a 5 second time window is allowed,
     // and the HMAC must match.
-    if ($time_diff >= 0 && $time_diff <= 5 && $hmac === $test_hmac) {
+    if ($time_diff >= 0 && $time_diff <= 180 && $hmac === $test_hmac) {

The comment is now out of sync, please update it. We should mention why we check for 180.

I'm not too happy about the fix since it just fixes the symptom by increasing the time limit. Why do we have the time limit here in the first place? What could a replay attack look like that we need this?

Lendude’s picture

@klausi thanks for the feedback, the patch wasn't really written with a 'lets get this committed' mindset, more with a 'lets try to understand what is going on here' thing in mind, I'll update it once we figure out what to do here.

Why do we have the time limit here in the first place? What could a replay attack look like that we need this?

I would imagine that a replay attack would use the info in the cookie to do more request against the test site. But since the info in the cookie is also dependant on the info in the .htkey file, that gets rebuild for every test method, the info in the cookie is only valid as long as the current test method is running anyway.
So adding another timeout on top of that does seem pretty redundant.

dawehner’s picture

For me its not only #23, but there is also the fact that this all doesn't depend on a system without a running simpletest instance.

klausi’s picture

Issue tags: -Needs security review

I looked at the code and from my understanding a replay attack scenario has quite some requirements:

1. Simpletest must have been used on a production site.
2. An attacker got into possession of a test HTTP request that the site has sent locally to itself during testing. Which is not possible for a remote attacker, so they must have access to the server already to capture requests.
3. Simpletest did not shut down correctly and failed to clean up the test directory. It has to leave a settings.php file and .htkey behind in the file system.
4. The attacker finds a weakness to break out of the child test site and get access to the database of the main site. I can't think of a way to accomplish that, but would be very curious to see creative attempts :-)

Given that at least 2. makes an attack not practical I think the timestamp check is redundant and can be removed.

Lendude’s picture

Status: Needs work » Needs review
FileSize
1.88 KB
3.59 KB

@klausi Thanks!

Patch without a timestamp in the SIMPLETEST_USER_AGENT cookie.

chx’s picture

Recommended based on the original issue: ask pwolanin instead of me. (note that the git commit message is broken and refers to #3518404 instead of #518404 but this is the issue without a doubt, Dries accidentally typed an unshifted # after the # in the commit message)

klausi’s picture

Status: Needs review » Needs work

I pinged pwolanin to check this issue.

Patch looks good, some nitpicks in the meantime:

  1. +++ b/core/includes/bootstrap.inc
    @@ -638,11 +638,9 @@ function drupal_valid_test_ua($new_prefix = NULL) {
    +    // Check that the HMAC match.
    

    "matches"

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Session/SessionTest.php
    @@ -0,0 +1,58 @@
    +  /**
    +   * @var User
    +   * The current logged in user.
    +   */
    +  protected $user;
    

    This variable is never used and can be removed.

  3. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Session/SessionTest.php
    @@ -0,0 +1,58 @@
    +    $this->user = $this->drupalCreateUser([
    +      'administer site configuration',
    +      'access administration pages',
    +      'access content overview',
    +    ]);
    +    $this->drupalLogin($this->user);
    

    This can just be a local variable $user, since we never use it later.

I wonder if we should mention drupal_valid_test_ua() in the test case comment somewhere to leave behind a hint why we have this test?

pwolanin’s picture

I really don't think we should remove this time check completely since in addition to replay protection, it also offers some protection against brute force attacks. If possible, we should make the whole mechanism stronger. It seems there is a suggestion of writing a temp file with a random value also? I'm not sure who that will work for a parallel test run? We don't want to rely on user input in the header to find the file.

I think dawhner has a good suggestion of also making sure the simpletest module is enabled, if we don't already check that?

klausi’s picture

We are already writing a file with a random value: the .htkey file we are using, or do you mean something else?

As I said: an attacker cannot perform a replay attack because they can never capture the local request the test system performs on itself. So we are protecting something that cannot be exploited anyway, unless I'm missing something.

If we want to have better protection against brute force attacks then we can simply make our private .htkey longer.

Simplestest module does not have to be enabled when phpunit browser tests are executed, so we cannot check for that.

klausi’s picture

Addressed my nitpicks and made the .htkey private key longer to better protect against brute force attacks.

Does that address our concerns sufficiently? (I would really like to avoid raising the time limit, because then people will just run into this problem later again when they have long running tests)

slashrsm’s picture

Looks good to me. Based on the discussion it seems that this still provides sufficient level of security.

Thank you all!

Lendude’s picture

One more minor tweak, the content view doesn't have ajax enabled, so no need to wait (leftover bit from one of my earlier debug attempts).

klausi’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Drupalaton

Looks good! It seems we have agreement from several people here and addressed the concerns. @pwolanin: feel free to push back if you see something we missed.

alexpott’s picture

We can't check if the simpletest module is enabled because under 99.9% of tests it is not enabled on the child site. I agree with @klausi now we've added the .htkey we're fine. Another thing to look at in the future is to move all the drupal_valid_test_ua stuff into middleware that is only added by test system when it writes the settings.php for the child site. Thereby making it impossible for the parent site to ever become a test site.

dawehner’s picture

Here is a quick followup: #2783125: Exploring to move drupal_valid_test_ua() functionality into a middleware

+++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Session/SessionTest.php
@@ -0,0 +1,54 @@
+    $this->drupalGet('admin/content');
+
+    $session_assert = $this->assertSession();
+
+    $page = $this->getSession()->getPage();
+
+    for ($i = 0; $i < 15; $i++) {
+      $page->clickLink('sort by Title');
+      $session_assert->statusCodeEquals(200);
+    }

We could make this more explicit by sleeping for some seconds and not using views, but I'm not convinced this should block this patch.

pwolanin’s picture

Status: Reviewed & tested by the community » Needs work

The test prefix is sent in the headers, so a file upload vuln could possibly be leveraged into a site install vuln?

I don't think the threat and security model here is sufficiently fleshed out or documented.

If we don't want to check a timestamp in the UA header, maybe we should check the ctime of the .htkey file? certainly there should be a reasonably short limit to its validity (minutes)? If a bug or fatal error mean it's not cleaned up and we allow a replay attack by removing the timestamp check, then that's a new vuln avenue?

Should we use the inode number of the .htkey file instead of in addition to ctime of the code file?

The prefix is currently a 10 digit number (?), and that's used for the path to the .htkey file.

klausi’s picture

Status: Needs work » Needs review

I don't understand your point about the prefix. Code in drupal_valid_test_ua():

if (isset($user_agent) && preg_match("/^(simpletest\d+):(.+):(.+):(.+)$/", $user_agent, $matches)) {
    list(, $prefix, $time, $salt, $hmac) = $matches;

So $prefix must always be a string starting with "simpletest" and then having only digits. There is no way for an attacker to supply a malicious prefix that would contain other characters that are necessary to read data from an attacker supplied key file. Maybe I'm missing something and you can point that out?

Checking the ctime of the .htkey: that would then be the same timestamp check we are doing now, and we would potentially run into this same problem again with long running tests.

About replay attacks: we have already established that they are not possible, because an attacker would have to capture requests to replay them. Since the site is sending requests locally to itself the attacker would need to have access to the server already to catch them there. Can you elaborate on the replay attack scenario you think would be possible?

Inode number: we are already using it, please check the code in drupal_valid_test_ua().

I'm setting this back to needs review to indicate others should have a look as well, but given that there is no new info about potential attack scenarios I think we can go back to RTBC?

dawehner’s picture

Checking the ctime of the .htkey: that would then be the same timestamp check we are doing now, and we would potentially run into this same problem again with long running tests.

Right, let's assume we would have the ConfigImportAllTest and use an actual browser for that, we would probably run into those timestamp issues as well. For me its also a bit of a problem to have a slightly different behaviour in a test compared to a real site. You never know what kind of problems might come out of that ...

klausi’s picture

This issue is now blocking all browser test conversion issues from #2735005: Convert all Simpletest web tests to BrowserTestBase (or UnitTestBase/KernelTestBase).

Can someone else confirm my analysis and put this back to RTBC?

pwolanin’s picture

I don't think this is RTBC. A fatal error that leaves a .htkey file behind would allows a replay attack?

I think we need a doc page that goes through the threat model and how possible problems are mitigated?

alexpott’s picture

I tried out the idea in #35... didn't work unfortunately.

alexpott’s picture

Why don't we just bump the timeout to 180 seconds to start with? And open another issue to discuss removing it - so at least we get to fix the current issue. Because to be honest whether it's 5 or 180 it should be fine.

dawehner’s picture

There is still a potential of random failures for some long interactions on the screen, but its hopefully less likely.
I imagine for example a fully tested outside in workflow to potentially take longer than 3 minutes.

Lendude’s picture

Why don't we just bump the timeout to 180 seconds to start with? And open another issue to discuss removing it

+1

I imagine for example a fully tested outside in workflow to potentially take longer than 3 minutes.

Well there is a workaround of just calling prepareRequest() on a regular basis. It's not realistic to this in all tests, but in exceptionally long running tests, which will probably be rare, it's probably fine for now, right?

klausi’s picture

Status: Needs review » Needs work

@pwolanin: I repeat for the third time: a replay attack is not possible because an attacker cannot capture the requests. See my previous comments.

And I was thinking about possible threat models and attack vectors already, see my previous comments. If you know of anything more please mention it here, otherwise we would just have an empty doc page? It looks like we are operating on FUD here.

OK I give up - for the sake of making progress let's just increase the timeout. I propose something higher to not run into this timeout again too soon ==> how does 10 minutes == 600 seconds sound?

klausi’s picture

Here is a patch increasing the time limit to 10 minutes, including a comment pointing to this issue that the time check should be removed in a future version.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you @klausi
I would have commented earlier, but I don't just feel comfortable with that security question, even if I agree with your analysis.

pwolanin’s picture

@klausi - I'm not trying to spread FUD, but saying that a replay is "impossible" ignores that many silly things that people do in the real world.

A doc page about this shouldn't be empty if we actually explain how it works and what threats are considered.

I still think adding a check on the time of the .htkey file would harden this whole system more usefully.

claudiu.cristea’s picture

+++ b/core/includes/bootstrap.inc
@@ -640,9 +640,13 @@ function drupal_valid_test_ua($new_prefix = NULL) {
+    // @todo the additional time check appears to not add any security and can
+    // cause random test fails for long running tests. See the discussion in
+    // https://www.drupal.org/node/2771547 for why it should be removed in a
+    // future version.

Nit: @todo additional lines should be indented.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/includes/bootstrap.inc
    @@ -640,9 +640,13 @@ function drupal_valid_test_ua($new_prefix = NULL) {
    +    // @todo the additional time check appears to not add any security and can
    +    // cause random test fails for long running tests. See the discussion in
    +    // https://www.drupal.org/node/2771547 for why it should be removed in a
    +    // future version.
    

    Let's not add this @todo - the facts of this have been disputed so let's not add it.

  2. +++ b/core/includes/bootstrap.inc
    @@ -640,9 +640,13 @@ function drupal_valid_test_ua($new_prefix = NULL) {
    +    if ($time_diff >= 0 && $time_diff <= 600 && $hmac === $test_hmac) {
    

    I think we should throw an exception exception in the case the timeout is exceeded. So it is easy to track down the test that has caused it. Obviously we shouldn't given any helpful info to the attackers.

  3. It's weird that we through an exception if the htkey file is not readable but just don't set the test prefix if the time limit is up.
klausi’s picture

Status: Needs work » Needs review
FileSize
2.42 KB
913 bytes

We do not throw an exception when the .htkey is not readable, we just return 403 and exit immediately. Of course it makes sense to do the same when timeout or HMAC are wrong.

Also removed the @todo, but we still haven't collected even one attack scenario that would work without the timestamp check.

ndf’s picture

+++ b/core/includes/bootstrap.inc
@@ -640,11 +640,15 @@ function drupal_valid_test_ua($new_prefix = NULL) {
-    // Since we are making a local request a 5 second time window is allowed,
+    // Since we are making a local request a 600 second time window is allowed,

We had 5 seconds, we went to 600.
Should we validate how long the test-suite runs?
Mentioned by #36

Like

// After 600 seconds/10 minutes a session must expire.
$page = $this->getSession()->getPage();
  page->clickLink('sort by Title');
  $session_assert->statusCodeEquals(200);

wait(550);
  $page->clickLink('sort by Title');
  $session_assert->statusCodeEquals(200);

wait(600);
  $page->clickLink('sort by Title');
  $session_assert->statusCodeEquals(403);

A timeout-test gives an upper-limit for all other tests.
It might help analyze future test-failures.

#52 Not a security expert and I don't know an attack scenario. But I do see a 120x stampede attack surface if you get through #25.

dawehner’s picture

One problem with waiting for that long is that it would slow down potentially the entire test suite for quite a while.

alexpott’s picture

I'm not in favour of a test

+++ b/core/includes/bootstrap.inc
@@ -640,11 +640,15 @@ function drupal_valid_test_ua($new_prefix = NULL) {
+      header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
+      exit;

Should we add information that this is due to an invalid SIMPLETEST_USER_AGENT? I don't think that that would give an attacker anything since they already know this...

And I'm definitely -1 to 10 minute test doing nothing.

dawehner’s picture

Should we add information that this is due to an invalid SIMPLETEST_USER_AGENT? I don't think that that would give an attacker anything since they already know this...

Yeah, I mean if they want to use this, non existing vulnerability, they already, due to the header prefix, know exactly what they are dealing with.

@alexpott
Would you be okay with a test which sleeps for 6 seconds?

alexpott’s picture

@dawehner not adverse to such a test... but I'd rather just bump the number of clicks to the test added here...

dawehner’s picture

@dawehner not adverse to such a test... but I'd rather just bump the number of clicks to the test added here...

For me this clicking is kind of a really implicit test.

Lendude’s picture

As @dawehner pointed out before, it was never good that the test required views and an existing non-test view. So quick reroll to get rid of the views dependency and I think this makes it much clearer what's going on here.
Just a link in a menu on the front page that links back to the front page. Endless looping clicky fun!

klausi’s picture

Status: Needs review » Needs work

It is important to perform the test as logged-in user, so that the page caching does not get in the way.

I think clicking a couple of times is the right approach, since that is the actual problem we ran into when doing multiple requests with Mink. 50 times seems a bit high, but good enough for me.

+1 on printing a message with the 403 saying the SIMPLETEST_USER_AGENT is invalid.

Lendude’s picture

Status: Needs work » Needs review
FileSize
839 bytes
2.67 KB

Logged in a user, and yeah the reason I cranked up the number of clicks was because it took more clicks to show the error due to the caching, so turned it down to 25.

+1 on printing a message with the 403 saying the SIMPLETEST_USER_AGENT is invalid.

Not sure how we want to do that, so leaving that for somebody else for now.

alexpott’s picture

Status: Needs review » Needs work

If we do something like:

header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden (SIMPLETEST_USER_AGENT invalid)');

Would work.

klausi’s picture

I just looked at RFC 2616 and we are allowed to change the reason phrase in HTTP: "The reason phrases listed here are only recommendations -- they MAY be replaced by local equivalents without affecting the protocol."

So yes, alex' suggestion should be ok.

Lendude’s picture

Status: Needs work » Needs review
FileSize
389 bytes
2.7 KB

Ok, lets do that then.

Shame it's not shown in the error output, would have been nice.

There was 1 error:

1) Drupal\FunctionalJavascriptTests\Core\Session\SessionTest::testSessionExpiration
Behat\Mink\Exception\ExpectationException: Current response status code is 403, but 200 expected.
dawehner’s picture

+++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Session/SessionTest.php
@@ -0,0 +1,61 @@
+    for ($i = 0; $i < 25; $i++) {
+      $page->clickLink('Link to front page');
+      $session_assert->statusCodeEquals(200);

I still think that explicit waiting and then clicking once would be better to read.

For example wait for 6 seconds, and then click a link

Lendude’s picture

@dawehner I think that would be a better explicit test for the fix, but I do think the actual issue we are trying to fix here is not being able to do enough consecutive actions before something goes wrong. With a 6 second test, you could introduce a 7 seconds timeout and everything would be green, but the same issue of not being able to do enough consecutive actions would be back.
So in that light I think the current test is pretty valid.

klausi’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, thanks! I also think the test case with clicking multiple times is valid.

dawehner’s picture

@dawehner I think that would be a better explicit test for the fix, but I do think the actual issue we are trying to fix here is not being able to do enough consecutive actions before something goes wrong. With a 6 second test, you could introduce a 7 seconds timeout and everything would be green, but the same issue of not being able to do enough consecutive actions would be back.
So in that light I think the current test is pretty valid.

Well, when you don't do at least something for +5 seconds, you haven't written a test which ensures that this issue continues to work. Well, I don't care :)

dawehner’s picture

Here is a new followup to discuss the removing again: #2790439: Remove drupal_valid_ua() time protection

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed ee38d6f to 8.3.x and 2a4eab9 to 8.2.x. Thanks!

  • alexpott committed ee38d6f on 8.3.x
    Issue #2771547 by Lendude, klausi, dawehner, alexpott, pwolanin: In...

  • alexpott committed 2a4eab9 on 8.2.x
    Issue #2771547 by Lendude, klausi, dawehner, alexpott, pwolanin: In...

Status: Fixed » Closed (fixed)

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