Problem/Motivation
Elements of #type => password_confirm
do not respect t#maxlength
attribute. The user can enter more than the specified length and no validation errors are thrown.
In 10.2.4
If #maxlength is specified there is an additional crash in validate handler
The website encountered an unexpected error. Try again later.
TypeError: mb_strlen(): Argument #1 ($string) must be of type string, array given in mb_strlen() (line 333 of core/lib/Drupal/Core/Form/FormValidator.php).
Drupal\Core\Form\FormValidator->performRequiredValidation(Array, Object) (Line: 246)
Drupal\Core\Form\FormValidator->doValidateForm(Array, Object) (Line: 238)
Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'FlowerAjaxBugForm') (Line: 118)
Drupal\Core\Form\FormValidator->validateForm('FlowerAjaxBugForm', Array, Object) (Line: 593)
Drupal\Core\Form\FormBuilder->processForm('FlowerAjaxBugForm', Array, Object) (Line: 325)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 627)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 32)
Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 36)
Drupal\Core\StackMiddleware\AjaxPageState->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Steps to reproduce
1. Create a custom form with an element of type password_confirm
2. Set #maxlength attribute for the element to 10
3. In the UI enter a value more than 10 characters, it's accepted
4. Submit the form, it crashes with the above error
Proposed resolution
Element of type password_confirm should support #maxlength attribute. Validation error must be thrown if the user enters value more than the specified characters.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
Comment | File | Size | Author |
---|---|---|---|
#85 | confirm_password maxlength 15.png | 121.33 KB | sukr_s |
#73 | interdiff_71_73.txt | 3.91 KB | Eduardo Morales Alberti |
#73 | core-password_confirm_support_maxlength-1344552-73.patch | 8.64 KB | Eduardo Morales Alberti |
#52 | Before Patch 1344552.png | 586.13 KB | chetanbharambe |
#51 | Screenshot from 2021-05-26 10-42-40.png | 47.62 KB | vikashsoni |
Issue fork drupal-1344552
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
Ravi.J CreditAttribution: Ravi.J commentedPatch attached
Comment #2
Ravi.J CreditAttribution: Ravi.J commentedComment #2.0
Ravi.J CreditAttribution: Ravi.J commentedrephrased some of the lines in issue body text to make it easier for reader to understand
Comment #3
Everett Zufelt CreditAttribution: Everett Zufelt commentedI haven't tested, but the use case and the code seem good to me.
I don't know what the API backport policy is, but I see no reasons for this not to be backported to D7.
Comment #4
Ravi.J CreditAttribution: Ravi.J commentedI am changing this one to Major bug as the issue results is password_confirm field type not being usable.
Since opening this ticket, i have had two different projects on which i had to use different password fields instead of password_confirm
Comment #5
xjmI may be missing something, but how does missing #maxlength make the field unusable?
Comment #6
Ravi.J CreditAttribution: Ravi.J commentedAs password_confirm field does not support #maxlength property, There is no way to restrict how many characters users can input in the field. Even in situation where the underlying database field only accepts a limited number of characters, it cannot be enforced within form.
The result of this is
1. Developers needs to enforce maximum characters limit in
_validate hook.
2. User's are still allowed to enter unlimited number of characters and get error message back only after form is submitted. This makes for such a bad user interface , they should not have been allowed to enter more than allowed number of characters in first place.
The only option to solve above issue to use two separate password fields (As posted above in original usecase) which makes password_confirm field type unusable and redundant.
Also password_confirm field is rendered as HTML password element, and should support maxlength prooperty as per guidelines http://www.w3.org/TR/html4/interact/forms.html#adef-maxlength
Looking through core code, i see that password_confirm field is suppose to work exactly like password field, and all it should do is to make a copy of password field and apply additional validation rule, At the moment this is not the case and needs to be fixed.
Comment #7
cweagansTalked to RaviJ in IRC, and this is indeed a pretty big Drupal WTF.
The problem is that a password field on it's own DOES support maxlength, while the password_confirm field type (which renders as two password inputs) does NOT.
That's the problem to solve here, and RaviJ's patch fixes the problem well.
Comment #8
cweagansThis should be backported to 7.x, and potentially 6.x, but I'm not sure.
Comment #9
xjmOkay, we need an automated test then. Thanks @cweagans and @Ravi.J!
Comment #10
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedHere is a testcase verifying the problem.
Note that even with the patch the full-length value is passed to the submit handler and some notices occur - at least locally.
Edit: When doing a reroll, note this typo:
Should be: Validation fails.
Comment #11
xjmExcellent. Pending testbot, I think the tests look great, aside from the comment typo @Niklas Fiekas points out. Edit: and "secound."
Edit 2: Sorry, misread the comment above. This is the error message:
Warning: mb_strlen() expects parameter 1 to be string, array given in drupal_strlen() (line 444 of /home/niklas/Projekte/drupal-8/core/includes/unicode.inc).
So presumably we'll see that fail on the combined patch.
Comment #13
marcingy CreditAttribution: marcingy commentedThe exceptions are generated because in _form_validate the password field is an single element with multiple #values in the form of an array so we need to some how make an exception. The obvious option is add additional logic to see if #value is an array and if so we then do the max length check on each element within the array when submitting.
Comment #14
marcingy CreditAttribution: marcingy commentedLets see how this goes
Comment #15
marcingy CreditAttribution: marcingy commentedMissed the comment above first time round this patch just fixes the comment
Comment #16
marcingy CreditAttribution: marcingy commentedmeh
Comment #17
xjmThanks @marcingy, and thanks @Niklas Fiekas for providing a complete test so we can make sure we get the right solution. Looks like it should pass based on #14.
Meanwhile, one suggestion:
Rather than duplicating the code here, I think it would be better to do something like:
and then foreach $foo.
(Edited to correct the pseudocode.)
Edit 2: Wait, do we really want to set an error for every item? Wouldn't one error be sufficient? Maybe we should
break;
?Comment #18
xjmTagging for UX sanity check once we have a working solution. :)
Comment #19
David_Rothstein CreditAttribution: David_Rothstein commentedPer the definitions at http://drupal.org/node/45111 this is not a major bug. It's arguably not a bug at all (since it's documented behavior), although for consistency it definitely makes sense to change.
Couple issues:
'%length' => $element_value
should be'%length' => drupal_strlen($element_value)
so that the correct thing is printed.Note sure if it's an official coding standard, but I think we usually use "elseif" in PHP code?
I think we do want the red border around each item, although it looks like the code will probably do that even if only one error is set... When I tested the patch, I also expected to see a problem where two error messages were displayed. For some reason, though, only one error message is displayed (even though two errors are set); I didn't track down why. We definitely only want one error message. I think this ties into my comment #2 above; are we actually validating them separately or really just validating the whole thing as a group?
Comment #20
David_Rothstein CreditAttribution: David_Rothstein commentedTo partially answer my question in #2, I guess the deal is that each sub-element has to have its own #maxlength in order for it to actually be printed in the HTML...
Still seems odd at least in the password confirm use case, since you'd never want the two elements to have different #maxlengths there.
Comment #21
xjmYep: http://drupal.org/coding-standards#controlstruct
And regarding #2, changing all of
_form_validate()
for this does seem a bit odd, and there's certainly no reason you'd have a different maxlength for the confirm password field vs. the password. I don't even know what it would mean outside this context.Edit: xpost.
Comment #22
marcingy CreditAttribution: marcingy commentedAs I got into this to be honest I agree it seems much more like a task/feature request than a bug, and if you need to validate field length in password hook validate can be utilised. And after the comments above it seems like we really need to refractor how the password element works.
Comment #23
cweagansUpdating tags per http://drupal.org/node/1517250
Comment #24
pjcdawkins CreditAttribution: pjcdawkins commentedRelated issue: #111322: Create #confirm property to ensure equality of two input fields
Comment #25
YesCT CreditAttribution: YesCT commentedI think we need to look at this to see if things have changed in 8.x
And we need to decide on an approach to take.
Updating the issue summary to reflect that needs screenshots is waiting on a new patch.
Issue summary also needs updating to summarize different possible approaches to take.
Comment #25.0
YesCT CreditAttribution: YesCT commentedReformatted body text to make the issue easier to understand
Comment #26
YesCT CreditAttribution: YesCT commentedActually, screenshot could be made of the page that will change. We can get the *before* screenshot to show what it looks like right now. That would also be a good chance to document the steps to reproduce of how to get to that page.
Comment #26.0
YesCT CreditAttribution: YesCT commentedclarified nothing right now to do screenshots of
Comment #27
Ravi.J CreditAttribution: Ravi.J commentedScreenshots of they look at the moment already attached in the original issue post.
The fundmental problem is that, when a password confirm field is used in form API, two separate text field are rendered with different max length properties.
This is a bug. It doesn't seem logical to write form validators for the problem and agree with #21 that it does seem odd to write all the validators.
Comment #27.0
Ravi.J CreditAttribution: Ravi.J commentedbefore screenshot can be made
Comment #34
andypostComment #35
aleevasLooks like we need to redo this whole patch, cuz we don't have these test files and the function "_form_validate" in the core/includes/form.inc
Comment #36
aleevasSo I added a new one.
Comment #38
andypost@aleevas patch should be applicable with `patch -p1`! your one is `-p0`
Comment #39
andypostComment #40
zahord CreditAttribution: zahord as a volunteer and at Skilld commentedpatch #36 was updated
Comment #41
zahord CreditAttribution: zahord as a volunteer and at Skilld commentedComment #46
tanubansal CreditAttribution: tanubansal at Salsa Digital commentedPatch is not working on 9.1
Please check
Comment #47
raman.b CreditAttribution: raman.b at OpenSense Labs commentedResolving failed test cases from #40
Comment #49
Ruchi Joshi CreditAttribution: Ruchi Joshi at Srijan | A Material+ Company for Drupal India Association commentedThis issue doesn't exists for drupal 9.1. Max limit for Confirm Password and Password field is set to 128 characters and it automatically crops character to it.
Screenshot is attached
Steps:
1. Visit /admin/people/create
2. Enter a long text of 200 characters on Password field.
3. When cursor is out from Password field, it will automatically crop the text by 128 characters.
4. Enter a long text of 200 characters on Confirm Password field.
5. Again cursor is out from Confirm Password field, it will automatically crop the text by 128 characters.
6. Similarly, we can try with User profile update form- /user/4/edit, but result will be same as in pt. 3 & 4
Comment #51
vikashsoni CreditAttribution: vikashsoni as a volunteer and at Zyxware Technologies commentedthere is no issue exists for drupal 9.3. Max limit for Confirm Password and Password field is set to 128 characters and it automatically crops character to it.
Screenshot is attached .................
Comment #52
chetanbharambe CreditAttribution: chetanbharambe at QED42 for Drupal India Association commentedVerified and tested this issue on the 9.3.x-dev version.
Working as Expected.
Testing Steps:
# Goto: Appearance -> Apply Seven Theme
# Goto: /admin/people/create
# Enter a long text of 200 characters on the Password field.
# When the cursor is out from the Password field, it will automatically crop the text by 128 characters.
# Enter a long text of 200 characters on Confirm Password field, it will automatically crop the text by 128 characters.
# Observe the results
Expected Results:
# Verified that Max limit for Confirm Password and Password field is set to 128 characters and it will automatically crop characters to it.
Note: This issue is already FIXED on this (9.3.x-dev) version, So we can close this issue.
Please refer attached screenshots for the same.
Looks good to me.
Can be a move to RTBC.
Comment #55
sonam.chaturvedi CreditAttribution: sonam.chaturvedi at Salsa Digital commentedThis issue doesn't exists for drupal 9.5.x-dev.
1. Password confirm field type now have support for #maxlength attribute
2. Max limit for Confirm Password and Password field is set to 128 characters and it automatically crops character to it.
3. User is able to login using 128 character password (even when 200 is entered while creating user account)
No patch required, moving to RTBC
Comment #56
rkollerI've taken a look in 9.5.0-dev and I can confirm that the password fields have a
maxlength
attribute of128
. In contrast the latest patch in this issue added a maxlengh of 12 only? In regards of the issue status I wouldn't set it to RTBC but Closed (Outdated).But in regards of the observations @sonam.chaturvedi made in #55.2 & #55.3. I have manually tested and have a few differing observations:
password
andconfirm password
field. None of the two fields notified me that I've exceeded the maximum password length. I was able to successfully save the password changes afterwards. I've then logged out and tried to relogin. First with the first 128 characters of the 138 character password, that failed so the password isn't cropped. I was able to login using the 138 characters password. That is a consider a good thing. Cropping a password without any notification at all silently i would consider a ux no-go. but still the maxlength attribute has no effect at all and should be fixed.password
,password
andconfirm password
field. I've then added one or two extra characters to theconfirm password
field. The password match remained to yes. Same when I've then added extra characters to the password field. It looks like as soon as the password length exceeds 128 characters the password match check isn't applied anymore and remains to yes all the time?i've tested in the latest safari, firefox and edge - all behave the same. I am setting the issue to needs work to get feedback on #55 and my comment. Uncertain what the best approach would be. Closing this issue as outdated and opening a new one or repurposing it by updating the issue summary and deal with described issues in here?
Comment #59
Eduardo Morales AlbertiIn our case, we use client side validation that has its own maxlength validation and we need the patch to override the maxlength on the confirm password element.
Examples:
Comment #60
Eduardo Morales AlbertiAfter applying the patch I got the error:
Because the confirm password element has two values, and the Form validator expects to validate an int.
The single value is set on Password Confirm Validation, but after the maxlength validation (FormValidator).
Form validator.php
Comment #61
Eduardo Morales AlbertiComment #62
Eduardo Morales AlbertiComment #64
Eduardo Morales AlbertiChanged the value callback to get the right validation on maxlength.
Comment #66
Eduardo Morales AlbertiPatch from MR.
Comment #67
Eduardo Morales AlbertiStill working on the patch because of the error on install:
Comment #68
Eduardo Morales AlbertiPatch for 11x.
Comment #70
Eduardo Morales AlbertiComment #71
Eduardo Morales AlbertiSolve errors on the site install.
Comment #72
Eduardo Morales AlbertiReviewing tests failed:
Comment #73
Eduardo Morales AlbertiFixing tests, value callback now returns only the password 1 because the second password is only for validation, and the password confirm already validates it, and also it makes the max length validation from the core fail because it expects a string but the value callback returned an array with both values.
Comment #74
Eduardo Morales AlbertiAll tests passed, ready to review.
The changes on MR https://git.drupalcode.org/project/drupal/-/merge_requests/4290/diffs are the same that the patch https://www.drupal.org/files/issues/2023-07-03/core-password_confirm_sup...
Comment #75
sahil.goyal CreditAttribution: sahil.goyal as a volunteer and at Srijan | A Material+ Company for Drupal India Association commentedHi @Eduardo Morales Alberti, thanx for the patch
I Reviewed and tested the patch. Confirmed that the following changes have been made and works as expected as:
In the valueCallback() method, returns an empty string instead of an array with empty values if no input is provided.
In the processPasswordConfirm() method, the explicit setting of for element pass1 and pass2 has been removed to depends on the value callback. Additionally, the '#maxlength' attribute is now correctly set for both fields when the attribute is specified on the PasswordConfirm element.
After thorough testing, all changes are working as expected and the functionality working fine. Moving to RTBC
Comment #76
Eduardo Morales AlbertiComment #77
Eduardo Morales AlbertiNot the same issue, but could be related because are altering the same field.
Comment #78
quietone CreditAttribution: quietone at PreviousNext commentedI am doing triage on the core RTBC queue.
Thanks for working on this old issue!
This issue has no issue summary! The issue summary is the first thing a reviewer or committer will see as they start their work. In #5, xjm asks the question I am asking as well, why is this needed. That information should be in the issue summary. Issue summaries matter.
And I see that this is tagged for "Needs issue summary update" and "Needs screenshots". I am setting this o needs work for the issue summary update and screenshots.
I see that there is a recent MR and a patch. Which one is to be reviewed?
Comment #79
sukr_s CreditAttribution: sukr_s as a volunteer commentedComment #80
sukr_s CreditAttribution: sukr_s as a volunteer commentedComment #82
sukr_s CreditAttribution: sukr_s as a volunteer commented- I've updated the issue summary
- fixed the issue
- added test
Comment #83
smustgrave CreditAttribution: smustgrave at Mobomo commentedSeems to be multiple MRs and patches these need to be cleaned up for clarity.
Was previously tagged for screenshots but the User interface changes section is empty.
Have not reviewed.
Comment #85
sukr_s CreditAttribution: sukr_s as a volunteer commentedAdding screenshot #maxlength set to 15. UI doesn't allow more than 15 characters.
hidden older MR !4290
Pipeline has not run for MR !7188. How can I trigger this?