Problem/Motivation

I was checking this module as I needed an easy way to manage limiting user tries before blocking account.

Thanks for this module.

I just have a request, I realized after blocking the user, when they request for a new password link and use that to login, they are able to login but once they logout, they can't login again until the duration you've set has passed. Now is it possible maybe to clear the Expiration time for that user when they request a new link?

I realized when you click on "request a new password" link the identifier changes to just a user id not a user link with user id, and the status is changed to "Not Blocked" but when you try to login you are still blocked until the duration has passed.

I am new to Drupal sorry if my question is stupid

Steps to reproduce

1. Install flood control module.
2. Configure module, set "Username login limit" and "Username login time window" as you like.
3. Now try to login and put wrong password as per the limit you've set. (While on this stage check the flood unblock page, you will see the identifier is a link to a user profile).
4. Once you have exceeded the limit the account will be locked and you'll see this text with request a new password: "There have been more than 5 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password."
5. Click on request a new password and follow the user journey. (At this stage, check the status on the flood unblock page, you will realize that the identifier is now just a user id not a link and the status will be "Not Blocked" but still with "Expiration time" while previous entries with user id are still blocked.
6. Once you have set your new password you will be able to login, but because your "Expiration Time (check this on flood unblock page)" has not passed, try to logout and login again, you will realize that you are still blocked and you'll get that text again "There have been more than 5 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password."

Now question is, on the flood unblock page, last record was my user id with status unblocked and with Expiration time set why can't I login? (I think because Expiration time has not passed)

Proposed resolution

If possible, when the user request a new password, allow the user to login by removing Expiration time since the status is already set to unblocked

Command icon 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

Lehlohonolo created an issue. See original summary.

lehlohonolo’s picture

Issue summary: View changes
lehlohonolo’s picture

Issue summary: View changes
phpsubbarao’s picture

Hi Lehlohonolo,

Update login hook for clear the flood table for logged user.

Thanks,
Talla.

driskell’s picture

Status: Needs review » Needs work

I think ideally this would be behind a feature flag, but there's also some issues.

  $results = $database->select('flood', 'f')
    ->fields('f', ['identifier', 'timestamp', 'fid'])
    ->condition('identifier', "%" . $database->escapeLike(\Drupal::currentUser()->id()) . "%", 'LIKE')
    ->execute()
    ->fetchAll();

This would mean a user with ID 15 would clear the flood control for user 150, 215, 4156 etc. The query needs tightening.
It's also worth noting a lot of this code already exists in FloodUnblockManager so could be reused.

phpsubbarao’s picture

@Driskell,

Updated the condition, instead of like, using equal condition, of course code available in FloodUnblockManager , it won't usable for after reset the password to clear the flood info.

Thanks,
Talla.

phpsubbarao’s picture

Status: Needs work » Needs review
batigolix’s picture

Assigned: Unassigned » batigolix
batigolix’s picture

Assigned: batigolix » Unassigned
batigolix’s picture

Status: Needs review » Needs work

There are changes in this patch that are out of scope like

+/**
+ * @file
+ */
+

and

-  if(empty($value)){
+  if (empty($value)) {

If it doesnt exists yet, please create an issue for code styling issues instead.

This creates a log notice with only the url as message? Can you expand this, so it includes better information?:

+    \Drupal::logger('flood_control')->notice($request_uri);

Same here: instead of just printing some IDs, add a bit more information:

+  \Drupal::logger('flood_control')->notice(json_encode($results));

We already have a function to clear flood events: floodUnblockClearEvent. Can you re-use that instead of a new custom function _flood_control_clear_log ?

If I do not want this functionality on my website (because I really want this visitor to wait a couple of weeks before he can login in again), there should be a way to disable it. So, we would need a setting to enable/disable this functionality. Make it disabled by default.

yustintr’s picture

If I do not want this functionality on my website (because I really want this visitor to wait a couple of weeks before he can login in again), there is now a way to disable it. And removed the code style fixes.

batigolix’s picture

Status: Needs work » Needs review
batigolix’s picture

Status: Needs review » Needs work

This is improving.

But there is still a couple of issue with this patch:

1. This creates a log notice with only the url as message:

\Drupal::logger('flood_control')->notice($request_uri);

Can you expand this, so it includes better information?:

2. Same here: instead of just printing some IDs, add a bit more information:

\Drupal::logger('flood_control')->notice(json_encode($results));

3. We already have a function to clear flood events: floodUnblockClearEvent. Can you re-use that instead of a new custom function _flood_control_clear_log ?

+/**
+ * Custom function for clear the flood.
+ */
+function _flood_control_clear_log() {
+  $database = \Drupal::database();
+  $results = $database->select('flood', 'f')
+    ->fields('f', ['identifier', 'timestamp', 'fid'])
+    ->condition('identifier', $database->escapeLike(\Drupal::currentUser()->id()), '=')
+    ->execute()
+    ->fetchAll();
+  foreach ($results as $key => $value) {
+    $parts = explode('-', $value->identifier);
+
+    if (!empty($parts[0])) {
+      $query_delete = $database->delete('flood')->condition('fid', $value->fid);
+      $success = $query_delete->execute();
+    }
+  }
+
+  \Drupal::logger('flood_control')->notice(json_encode($results));
+}
samitk’s picture

Assigned: Unassigned » samitk

I am working on it.

samitk’s picture

Assigned: samitk » Unassigned
Status: Needs work » Needs review

Hi @batigolix,

I have removed log notices code as it looks like added for testing purpose only, as you mentioned in Point 1 and 2.

For point 3, i have updated the delete query code with the function floodUnblockClearEvent of flood_control.flood_unblock_manager service.

Thnaks
Samit K.

samitk’s picture

StatusFileSize
new2.9 KB
new916 bytes
batigolix’s picture

Status: Needs review » Needs work

After some testing your patch a bit more I realised this must be a Drupal core issue that someone must have ran into before
I found this issue, which addresses the same problem:
#992540: Nothing clears the "5 failed login attempts" security message when a user resets their own password

I suppose we don't need to solve this in Flood Control, agree?

batigolix’s picture

Status: Needs work » Postponed (maintainer needs more info)
Related issues: +#992540: Nothing clears the "5 failed login attempts" security message when a user resets their own password
batigolix’s picture

Status: Postponed (maintainer needs more info) » Closed (won't fix)