Problem/Motivation
The issue: #1521996: Password reset form reveals whether an email or username is in use fixed the enumeration of email addresses and usernames via the password reset form. This issue is a follow-up to apply the same fix to the password reset json endpoint in \Drupal\user\Controller\UserAuthenticationController::resetPassword.
Steps to reproduce
Run
curl -X POST 'https://mydrupalsite.dev/user/password?_format=json' \
-d '{"mail": "myemail@example.com"}'
if myemail@example.com does not correspond to an account then the following payload will be returned:
{"message":"Unrecognized username or email address."}
if myemail@example.com does correspond to an account but the account is blocked or not activated, then the following payload is returned:
{"message":"The user has not been activated or is blocked."}
if myemail@example.com does correspond to an active not-blocked account then an empty code 200 response is returned.
Proposed resolution
Make the "Unrecognized username or email address." scenario return an empty code 200 response, as in return new Response();, but log the error in watchdog.
Discuss whether to prevent enumeration of non-active/blocked accounts in another issue.
Remaining tasks
Review the attached patch.
User interface changes
Same empty response regardless of whether the user exists with an active account or does not exist at all.
This decreases usability for users since they might be resetting their password with the wrong email address and then wonder why they never get an email. Right now you immediately know that you typed in a wrong email address. However, decreased usability vs. better privacy is probably a tradeoff we accept.
API changes
Headless clients will need to be adjusted for the new response.
Data model changes
None.
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3261663
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 #2
shaundychkoComment #3
shaundychkoComment #4
shaundychkoComment #5
shaundychkoComment #6
shaundychkoThe attached patch fixes enumeration of active accounts. Enumeration of non-active/blocked accounts is a lower priority, and perhaps whether to fix that could be discussed in another issue?
Comment #7
shaundychkoComment #8
schillerm commentedHi there, I have reviewed and tested this patch.
Set up local testing site, Drupal version 9.4.0-dev, PHP 8.0.15.
Created test user Joe Blogs, ran the curl commands got the expected responses back (successfully recreated error).
Applied patch #6, ran curl commands again.
Running curl command for non existent user returns empty 200 and logs message in watchdog.
Running curl command for existing Joe Blogs user also returns 200 and logs to watchdog.
Running curl command for locked Joe Blogs account returns {"message":"The user has not been activated or is blocked."} as expected.
Looked over the patch code changes, seems ok to me but less confident in reviewing this.
Comment #10
cmlaraThe fail in #9 was a known random #3269085: [random test failure] Random test fail in EntityAutocompleteTest.
ShaunDychko added re-test on March 17th that passed.
Restoring #8's RTBC
Comment #11
dwwThanks for working on this important oversight from previous efforts to fix this bug! Hate to do this, but I don't think this is ready to commit. Point 1 is a dubious nit. Points 2 and 3 are in support of RTBC. But point 4 is why I think this at least needs more review, and possibly more work.
If we're going to add this as a local var, why not use it on the very next line?
At first, I wasn't sure this was in scope, but it's mentioned in the summary. We added similar logging at #1521996. This seems good.
I guess this is the equivalent of:
which is what we added.
The next few lines of this test are:
Doesn't that reveal the email address for blocked users exists? Is that not also a problem? Shouldn't we fix this as part of the same issue? That was part of what was originally fixed at #1521996: Password reset form reveals whether an email or username is in use for the web UI case.
Thanks again!
-Derek
Comment #13
dieterholvoet commentedComment #15
dieterholvoet commentedI processed dww's feedback and pushed everything to a MR. I also replaced the The user has not been activated or is blocked error message with a 200 response and an error log. I updated the tests to check for 200 responses, but shouldn't we also test whether the errors are logged? Not sure how to do that though, I came across #3274834: Allow functional tests to fail or expect logged errors but that doesn't seem like an option yet.
Comment #17
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Ran the tests locally without to the fix to make sure they failed. The response was really long but did fail
If that's something you want to test you could probably query the database.
Will move to NW for that but if it's actually not needed please send back.
Everything else looks good.
Comment #21
s.messaris commentedRerolled for 11.x and added the missing test scenarios
Comment #22
smustgrave commentedSeems the reroll caused test fialures.
Comment #23
s.messaris commentedWasn't the reroll, was the new test I added, I fixed it. Got an unrelated fail though, seems random, trying again.
Comment #24
s.messaris commentedTest bot seems to like this after all, back to review :)
Comment #25
smustgrave commentedChange looks good but I imagine there may be some pushback on
$logged = Database::getConnection()->select('watchdog')But not sure if there's a trait that can be used but will see
Good work everyone!
Comment #26
s.messaris commented@smustgrave I found it used like that 10 times across 4 files, not including the new addition, that's why I did it this way.
core/modules/comment/tests/src/Kernel/CommentIntegrationTest.php
core/modules/dblog/tests/src/Functional/DbLogTest.php
core/modules/dblog/tests/src/Kernel/DbLogTest.php
core/modules/system/tests/src/Functional/Form/StorageTest.php
Comment #27
smustgrave commentedHave no issue with it. Just have seen that get kicked back before.
Comment #28
larowlanHiding patches and updating issue credits
Comment #31
larowlanCommitted 98618df and pushed to 11.x. Thanks!
Backported to 10.1.x as this is an important security fix.
Added #3377275: Move \Drupal\Tests\system\Functional\Module\ModuleTestBase::assertLogMessage to a trait as a followup
Comment #32
larowlan