The first line of function user_login_authenticate_validate($form, &$form_state) {

should check if $form_state['uid'] is not null. If so it should simply return/exit the function at that point. The validate functions occur in this order:

user_login_name_validate
external authentication validate functions (0 or more)
user_login_authenticate_validate
external authentication validate functions (0 or more)
user_login_final_validate

so when the following sequence occurs:
user_login_name_validate [success]
external authentication validate functions [success, set form_state uid = N, log user in]
user_login_authenticate_validate [fail, set form state uid = FALSE]
user_login_final_validate [user warning is given and flood control not dealt with properly]

So the last step is broken for a user authenticating via an external means.

An outline of my validation workflow is at:
http://www.gliffy.com/publish/2362004/ in the upper right of the diagram

The design of the process is outlined in user.module about the user_login_default_validators function:

* Set up a series for validators which check for blocked users,
* then authenticate against local database, then return an error if
* authentication fails. Distributed authentication modules are welcome
* to use hook_form_alter() to change this series in order to
* authenticate against their user database instead of the local users
* table. If a distributed authentication module is successful, it
* should set $form_state['uid'] to a user ID.
*
* We use three validators instead of one since external authentication
* modules usually only need to alter the second validator.

This design is great and made the ldap module authentication sequence much simpler to implement; but without this fixed a successful logon with an external module does not work properly because user_login_final_validate gives them an error message.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

johnbarclay’s picture

a short term fix for other external authentication modules is to always put your validate functions after user_login_authenticate_validate in the validation array.

bfroehle’s picture

Status: Active » Needs work

The patch provided won't apply, as the diff was done in the wrong order. I think you mean to add, not remove, the early return in user_login_authenticate_validate().

Also, a brief comment about the code flow would be useful, e.g.,

  // No additional validation is required if a distributed authentication
  // module has successfully authenticated the user.

Lastly, the check should probably be !empty, as the distributed authentication module might want to log in a user with uid = 0.

johnbarclay’s picture

Status: Needs work » Needs review
FileSize
625 bytes

thanks. I rerolled the patch and added comments. I also used the !empty check as you suggested.

Status: Needs review » Needs work

The last submitted patch, user_login_authenticate_validate_uid_bug_fix2.patch, failed testing.

bfroehle’s picture

You'll have to read up on creating patches to make a patch that the test bot likes. Essentially you'll have to get it so that the top two lines are

--- modules\user\user.module
+++ modules\user\user.module

Also, the comment should adhere to the coding standards, meaning it should being with a capital letter, end in a period, and line break at 80 characters.

johnbarclay’s picture

Status: Needs work » Needs review
FileSize
498 bytes

updated patch

Status: Needs review » Needs work

The last submitted patch, user_login_authenticate_validate_uid_bug_fix2.patch, failed testing.

johnbarclay’s picture

Status: Needs work » Needs review
FileSize
488 bytes

Don't laugh at me; I'm using a new IDE.

Status: Needs review » Needs work

The last submitted patch, user_login_authenticate_validate_uid_bug_fix2.patch, failed testing.

bfroehle’s picture

Status: Needs work » Needs review
FileSize
600 bytes

John, I've fixed up the patch to put it in a conforming format for you.

I'm a little curious -- why not just alter the form and unset this validation function when the LDAP Auth module is enabled? If you need the function in your ldap auth login process, you could just call it directly.

johnbarclay’s picture

Thanks for fixing this.

Good question about the workaround. I can make ldap_authentication work simply by putting its validation function last. I can never replace user.module authentication because user 1 will always use it and the module supports mixed mode authentication so often many users are using user.module authentication.

The patch is more for other implementers of external auth modules; basically trying to reconcile the comments/design the the implementation in user.module. The other problem with messing with the validation sequence, is you don't know how other external authentication modules will mess with it. Its best if the behavior doesn't care about the order of validation functions.

The patch also makes it possible to predictably install more than one external auth module, by avoiding the need for the modules to reorder or remove validation functions.

dayer4b’s picture

subscribing

johnbarclay’s picture

My workaround in ldap_authentication for this works, but creates problems when other authentication modules or code come into play as identified earlier in this issue.

Without committing this, I don't see how 2 authentication modules can play well together. I suppose this should be a security issue since this leads to user authentication credentials being passed to multiple authentication tools in a way that contradicts the documentation.

I think thats a different issue process, so I'll look into that.

johnbarclay’s picture

Version: 7.0 » 8.x-dev
Status: Needs review » Active

This is continuing to present security issues in external authentication modules. If someone working on the user module in Drupal 8 could get this patch applied, we can backport it to 7.

The basic problem is that user_login_authenticate_validate() isn't implemented correctly. So it overwrites any successful authentication done by an external authentication module. In essence it makes the order of the validation critical. If a module wants to use mixed mode authentication it creates a nightmare because the external authentication module's validation function needs to also log the user on; otherwise it has to remove user_login_authenticate_validate from the authentication validators before the validation process starts. This is problematic since user_login_authenticate_validate() is doing flood control as well as drupal credential testing.

I don't have a drupal 8 install yet, but am still fighting this issue in the LDAP module in drupal 7.

Here's where the issue is:
http://drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/modul...

It should be
+ If (!empty($form_state['uid'])) {
$form_state['uid'] = user_authenticate($form_state['values']['name'], $password);
+}

This will allow the multi purpose user_login_authenticate_validate() function to behave in accordance with the user module validation requirements in http://drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/modul...

login_authenticate_validate() could be split into 2 functions also.

user_login_authenticate_validate_flood()
user_login_authenticate_validate_authentication()

The design is completely correct. Since external authentication modules can't know before the logon form is submitted, which validations succeed it can't know which validation functions to remove from the validation array. So setting $form_state['uid'] to signify success if very appropriate.

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

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

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

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

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

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

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

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

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

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

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

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

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

nithinkolekar’s picture

Issue summary: View changes

under https://api.drupal.org/api/drupal/core%21modules%21user%21user.module/8.5.x I don't see any *_validate function except user_validate_name.
what happened to those user_login_default_validators's methods?

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

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

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

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

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Lendude’s picture

Title: user_login_authenticate_validate function does not follow user module validation rules » \Drupal\user\Form\UserLoginForm::validateAuthentication function does not follow user module validation rules
Category: Bug report » Task
Issue tags: +Bug Smash Initiative

This came up as a Bug smash daily triage target

This has moved to \Drupal\user\Form\UserLoginForm::validateAuthentication but the premise is still the same, that method does 2 things, flood control and user authentication. Now, if I want to do flood control and not authentication, I can’t without duplicating lots of code. Which was basically done in \Drupal\basic_auth\Authentication\Provider\BasicAuth::authenticate, which is mostly the same, but slightly different.

So marking this as a task to refactor this and see if we can't make this more 1 method 1 responsibility and maybe not do the logic and code duplication with these two methods.

Lendude’s picture

Status: Active » Closed (duplicate)

@longwave pointed this one out #2431357: Extract a reusable UserAuthFlood service and reuse it in UserLoginForm and BasicAuth and UserAuthenticationController, closing this as a duplicate of that since that is the right direction for this and has been focussed on this since the start