According to issue #1921576, Drupal trims leading and trailing whitespace from the password field. However, leading and trailing whitespace in the password field increase password strength rating.

Steps:
1. Go to https://[domain]/user/[user#]/edit
2. In Password field, type abcde
3. Note length of indicator bar in Password strength (approx. 25%) and rating of Weak
4. Place cursor immediately before the first character
5. Type a space.

Actual result: Length of indicator bar increases to about 75% and rating changes to Good
Expected result: Length of indicator bar remains at about 25% and rating remains as Weak.

6. Backspace to remove the first character, or else blank the field and retype abcde
7. Place cursor immediately following the last character.
8. Type a space.

Actual result: Length of indicator bar increases to about 75% and rating changes to Good
Expected result: Length of indicator bar remains at about 25% and rating remains as Weak.

Verified in 7.x, but haven't confirmed in 8.x.

Comments

pushpinderchauhan’s picture

Assigned: Unassigned » pushpinderchauhan
pushpinderchauhan’s picture

Status: Active » Needs review
StatusFileSize
new1.81 KB

Here is patch added and fixed point: Length of indicator bar remains at about 25% and rating remains as Weak if either leading or trailing spaces is added. These extra spaces won't consider to calculate password strength.

pushpinderchauhan’s picture

Assigned: pushpinderchauhan » Unassigned
charles belov’s picture

The thing that bothers me about the current proposed solution code is that the same logic (stripping leading and trailing spaces) is duplicated in two places. I'm thinking that it would be better to have a single password filter function that is called by both the password saver and the strength checker. That way, if the filter is ever changed to allow keeping the beginning and end spaces, or to place other restrictions on the password, the processing will automatically change in both places. Does that make sense?

pushpinderchauhan’s picture

Yes Charles, I will create a single function to manage both cases. I will upload the next patch soon.

pushpinderchauhan’s picture

I have reviewed my code once again and found only following code can help in password strength checker. Because we have trimmed password value before passing in Drupal.evaluatePasswordStrength() function by
$.trim(passwordInput.val()).

After applying this code, I test this by creating new users and also edit existing users and its working fine as required.

Say I created a user with name "test", when user enter leading&trailing spaces in password fields then password strength checker dint comes into place. And at the time of saving in database, these leading&trailing spaces automatically get trimmed through module file. It means during password saver we don't required any function to deal this. So can we go with this single line or I need to write some other logic. Please correct me if I am wrong.

// Check the password strength.
        var passwordCheck = function () {
          if (settings.password.showStrengthIndicator) {
            // Evaluate the password strength.
            var result = Drupal.evaluatePasswordStrength($.trim(passwordInput.val()), settings.password);

            // Update the suggestions for how to improve the password.
            if (passwordDescription.html() !== result.message) {
              passwordDescription.html(result.message);
            }

            // Only show the description box if a weakness exists in the password.
            passwordDescription.toggle(result.strength !== 100);

            // Adjust the length of the strength indicator.
            innerWrapper.find('.indicator')
              .css('width', result.strength + '%')
              .css('background-color', result.indicatorColor);

            // Update the strength indication text.
            innerWrapper.find('.password-strength-text').html(result.indicatorText);
          }

          // Check the value in the confirm input and show results.
          if (confirmInput.val()) {
            passwordCheckMatch(confirmInput.val());
            confirmResult.css({ visibility: 'visible' });
          }
          else {
            confirmResult.css({ visibility: 'hidden' });
          }
        };
charles belov’s picture

I'm sorry. I now see the problem. The trimming for password strength is done in the browser via user.js, while the trimming for the database storage is done server-side via user.module. There is no way for them to both call the same function to do the trimming. Having to code the trimming code twice is unavoidable.

Please ignore my comment #4. You're patch #3 looks fine to me then.

Selected functions need to be replicable server- and client-side without having to code them in both server- and client-side code. But that is outside the scope of this issue.

aohrvetpv’s picture

Why not permit leading/trailing spaces in the password? Then there need be no special logic in the password-strength indicator, and users get the passwords they expect when they enter them.

aohrvetpv’s picture

I suppose some users might accidentally put spaces before or after their passwords, or assume that doing so has no effect. So it could also be confusing for some users if spaces are kept.

It seems it can be confusing no matter the password-strength indication (a problem probably more relevant to #1921576 than this issue).

charles belov’s picture

Re #8: I don't have any concern about leading or trailing spaces in passwords. But given that Drupal does strip them, it needs to not contribute to password strength.

I don't know why Drupal strips leading and trailing spaces - my guess is that it is intended to deal with inadvertently added spaces, e.g., through copy & paste - but having it not do so would be a separate issue from this one.

nod_’s picture

Status: Needs review » Needs work
Issue tags: +JavaScript

Instead of changing this in two different places in the code I would just add this line in Drupal.evaluatePasswordStrength function:

…   
    var username = (usernameBox.length > 0) ? usernameBox.val() : translate.username;

    password = password.trim();

    // Lose 5 points for every character less than 6, plus a 30 point penalty.
    if (password.length < 6) {
      msg.push(translate.tooShort);
      strength -= ((6 - password.length) * 5) + 30;
    }
…

And we can use the native trim function instead of using jQuery.

Also for reference if any issue is going to touch a javascript file can you please add the JavaScript tag to it so that the JavaScript team can monitor and review issues? Otherwise those kind of issues get lost in the queue.

mahtoranjeet’s picture

Assigned: Unassigned » mahtoranjeet
mahtoranjeet’s picture

Status: Needs work » Needs review
StatusFileSize
new502 bytes
yogen.prasad’s picture

Status: Needs review » Reviewed & tested by the community

Working fine

aohrvetpv’s picture

Status: Reviewed & tested by the community » Needs work

indentation

mahtoranjeet’s picture

Assigned: mahtoranjeet » Unassigned
Status: Needs work » Needs review
StatusFileSize
new500 bytes
nod_’s picture

Status: Needs review » Needs work

There is an eslint error:

core/modules/user/user.js
  114:14  error  Multiple spaces found before '='  no-multi-spaces

✖ 1 problem (1 error, 0 warnings)

Also usually when we change parameters like that we put this sort of thing at the very top of the function, before anything else gets done.

ashutoshsngh’s picture

Status: Needs work » Needs review
StatusFileSize
new499 bytes

Status: Needs review » Needs work

The last submitted patch, 18: Not-include-leading-and-trailing-spaces-2254235-18.patch, failed testing.

nod_’s picture

Could you move the new line at the begining please?

Right before var indicatorText; around line 112.

yogen.prasad’s picture

Status: Needs work » Needs review
StatusFileSize
new402 bytes
manjit.singh’s picture

StatusFileSize
new120.71 KB

Worked as expected Length of indicator bar remains at about 25% and rating remains as Weak.

Attaching screencast after applying patch.

manjit.singh’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +SrijanSprintNight
aohrvetpv’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new433 bytes

Also usually when we change parameters like that we put this sort of thing at the very top of the function, before anything else gets done.

Do you know an example of this offhand? It seems a little odd to me to call a function before variable declarations, though I am not an experienced JavaScript developer.

I see the logic of the suggestion--you look at the function parameters and can immediately see that parameter is being trimmed.

In any case, here is an updated patch that moves the line as you suggest. But the patch in #21 seems fine to me too.

Edit: I see now that nod_ is Drupal JavaScript maintainer so I defer to his judgment on the placement.

Status: Needs review » Needs work

The last submitted patch, 24: Not-include-leading-and-trailing-spaces-2254235-24.patch, failed testing.

aohrvetpv’s picture

Status: Needs work » Needs review
StatusFileSize
new388 bytes

Update to apply on latest code.

aohrvetpv’s picture

Is it a problem that trim() was introduced only in IE 9?

Edit: No, IE 9 or greater is required for Drupal 8 per https://www.drupal.org/node/61509.

droplet’s picture

Status: Needs review » Reviewed & tested by the community

Simple fix should not take such long time.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 26: Not-include-leading-and-trailing-spaces-2254235-26.patch, failed testing.

Status: Needs work » Needs review
aohrvetpv’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC per #28

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 4af9619 and pushed to 8.0.x. Thanks!

  • alexpott committed 4af9619 on 8.0.x
    Issue #2254235 by AohRveTPV, mahtoranjeet, er.pushpinderrana, yogen....
David_Rothstein’s picture

Version: 8.0.x-dev » 7.x-dev
Status: Fixed » Patch (to be ported)
Issue tags: +Needs backport to D7

From the issue summary it looks like this was originally discovered as a Drupal 7 issue.

aohrvetpv’s picture

Status: Patch (to be ported) » Needs review
StatusFileSize
new531 bytes

Drupal 7 requires IE 8 at minimum, but trim() was introduced in IE 9. So this patch uses replace() to accomplish nearly the same.*

*trim() actually removes some other obscure whitespace characters. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global..., which gives polyfill code for trim(). I doubt we care about them, but I have not investigated.

droplet’s picture

Status: Needs review » Needs work

D7 requires IE6+

jQuery.trim is your friend.

aohrvetpv’s picture

Status: Needs work » Needs review
StatusFileSize
new462 bytes

Thanks. I removed the comment since it is more obvious what the line is doing. Maybe it would be worth commenting why we are using jQuery.trim, though?

aohrvetpv’s picture

D7 requires IE6+

This "Browser Requirements" page seems to suggest IE 8 is the minimum:
https://www.drupal.org/node/61509

Do you know a source on 6 being the minimum supported IE version for Drupal 7? I don't think it matters for this issue, but it would be helpful to know.

droplet’s picture

Status: Needs review » Reviewed & tested by the community

It's officially dropped in D8:
https://www.drupal.org/node/1569578

David_Rothstein’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 7.x - thanks!

  • David_Rothstein committed f33147e on 7.x
    Issue #2254235 by AohRveTPV, mahtoranjeet, er.pushpinderrana, yogen....

Status: Fixed » Closed (fixed)

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