Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Remove username from email verification and password reset process #8488

Merged
merged 35 commits into from
Mar 2, 2025

Conversation

dblythy
Copy link
Member

@dblythy dblythy commented Mar 30, 2023

Pull Request

Issue

Currently, Parse Server exposes username via verification email urls. All that should be needed to perform a reset request is a valid token

Closes: #7137

Approach

Tasks

  • Add tests

@parse-github-assistant
Copy link

I will reformat the title to use the proper commit message syntax.

@parse-github-assistant parse-github-assistant bot changed the title fix: remove username from verification emails fix: Remove username from verification emails Mar 30, 2023
@parse-github-assistant
Copy link

Thanks for opening this pull request!

@dblythy
Copy link
Member Author

dblythy commented Mar 30, 2023

How should this handle expired tokens? With the old implementation the invalid verification link page could re-generate an email link.

I'm also wondering if removing the username parameter opens up to brute forcing, as previously to change a token you would need a valid username and token combination, whereas now you could brute for the endpoint with different tokens until one matches.

@codecov
Copy link

codecov bot commented Mar 30, 2023

Codecov Report

Attention: Patch coverage is 97.33333% with 2 lines in your changes missing coverage. Please review.

Project coverage is 93.55%. Comparing base (bbc6bd4) to head (e0e094c).
Report is 3 commits behind head on alpha.

Files with missing lines Patch % Lines
src/Routers/PagesRouter.js 88.23% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #8488      +/-   ##
==========================================
+ Coverage   93.53%   93.55%   +0.02%     
==========================================
  Files         186      186              
  Lines       14831    14834       +3     
==========================================
+ Hits        13872    13878       +6     
+ Misses        959      956       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@mtrezza
Copy link
Member

mtrezza commented Jun 17, 2023

How should this handle expired tokens? With the old implementation the invalid verification link page could re-generate an email link.

What is the purpose of token expiration for email verification? If an expired token leads to a website where one can request a new token (sent via verification email) without login, the expiration seems useless. Is there any scenario in which expiration makes sense? Maybe the existing tests related to token expiration give clues about the intentions of expiration?

I'm also wondering if removing the username parameter opens up to brute forcing, as previously to change a token you would need a valid username and token combination, whereas now you could brute for the endpoint with different tokens until one matches.

The difference of brute forcing two fields (email + token) vs one field (token) is just the amount of possible combinations. If we make the token a longer string, the difficulty should be the same.

What happens in the following scenario:

  1. User signs-up with email1
  2. Verification is sent to email1
  3. User changes email from email1 to email2
  4. Another verification email is set to email2
  5. Account of email1 is compromised
  6. Attacker open email1 verification link
  • Will the token for email1 be invalid?
  • Will that validate email2 with the token from email1?
  • Will that have any effect (changes) on the user object?

@dblythy
Copy link
Member Author

dblythy commented Jul 27, 2023

This PR:

  • Removes email from verification links
  • Makes it possible to regenerate links with a valid expired token (as previously this flow could be invoked with the username)

This all feels like pretty breaking changes to me, which I think we would have to phase in @mtrezza thoughts?

@mtrezza
Copy link
Member

mtrezza commented Jul 28, 2023

Did you find out any hinds regarding:

What is the purpose of token expiration for email verification? If an expired token leads to a website where one can request a new token (sent via verification email) without login, the expiration seems useless. Is there any scenario in which expiration makes sense? Maybe the existing tests related to token expiration give clues about the intentions of expiration?

Regarding breaking change:

  • I assume it would be breaking if someone has a verification email with an "old style" link and tried to open it after the developer upgraded Parse Server using the "new style" link. How should that be handled?
  • Are there any other breaking changes?

@mathieulb
Copy link

@mtrezza , if there isn't any code that specifically checks that the username is not in the link, and if tokens still work the same way, passing an old link to a new server will succeed. That is, if all cases of req.params.username have been removed and nothing does something like Object.keys(req.params).includes("username"). Right ?

@mtrezza
Copy link
Member

mtrezza commented Jan 27, 2025

@mathieulb That makes sense. Given that the existing tests have been changed, we'd need to maintain a test legacy test that uses the old link with username query parameter in the URL. Even though the param should be ignored, it would be good to test it.

@dblythy
Copy link
Member Author

dblythy commented Jan 28, 2025

What is the purpose of token expiration for email verification?

When you attempt to reset with an expired token, the server will throw. It's up to the client to request a renewal - previously you could do it with the email that is in the query params, but now that will no longer work (there is a new mechanism where you can submit the expired token for renewal)

@mtrezza
Copy link
Member

mtrezza commented Feb 3, 2025

I'm wondering; how long until an expired token is deleted from the DB? Or isn't it deleted at all? If it is deleted, then this logic probably fails and the correct approach would be to present a form with an email field where the user has to enter the email address. Or, just show a website which instructs the user on how to request a new verification email from within the app, if login with unverified email is enabled.

@dblythy
Copy link
Member Author

dblythy commented Feb 9, 2025

The expired token isn't deleted, it is just overriden by a new token. So it will only succeed the first time a resend is request, but will fail the next time (unless with the newer expired token)

@mtrezza mtrezza changed the title fix: Remove username from verification emails fix: Remove username from email verification and password reset emails Feb 12, 2025
@mtrezza
Copy link
Member

mtrezza commented Feb 12, 2025

We have talked about the impact on email verification, but this PR removes the username also from the password reset process, right? Changed the PR title. Are there any additions in the migration guide necessary? Any additional HTML page form changes?

Could you please take a look at the migration guide, I've made some changes, if that all makes sense?

@dblythy
Copy link
Member Author

dblythy commented Feb 19, 2025

Looks good. Only thing I would add is it only stores the most recent expired token. Previously with the username, multiple "expired links" could be re-validated. Now, we can only trigger the resend if the token was the most recent (as it is stored as a string)

@mtrezza
Copy link
Member

mtrezza commented Feb 19, 2025

Good point, that means with this change it is also recommended to set emailVerifyTokenReuseIfValid: true to reduce the likelihood of having to deal with expired tokens.

@dblythy
Copy link
Member Author

dblythy commented Feb 24, 2025

Updated docs

@mtrezza
Copy link
Member

mtrezza commented Mar 2, 2025

BREAKING CHANGE: This removes the username from the email verification and password reset process. If you are using customized HTML pages or emails related to email verification and password reset, they may need to be adapted accordingly. See the migration guide for more details.

Migration Guide

This is a major release with breaking changes. We prepared a migration guide to help you migrating from Parse Server 8. For the full list of breaking changes see the section below.

@mtrezza mtrezza changed the title fix: Remove username from email verification and password reset emails fix: Remove username from email verification and password reset process Mar 2, 2025
@mtrezza mtrezza merged commit d21dd97 into parse-community:alpha Mar 2, 2025
23 of 24 checks passed
parseplatformorg pushed a commit that referenced this pull request Mar 2, 2025
# [8.0.0-alpha.13](8.0.0-alpha.12...8.0.0-alpha.13) (2025-03-02)

### Bug Fixes

* Remove username from email verification and password reset process ([#8488](#8488)) ([d21dd97](d21dd97))

### BREAKING CHANGES

* This removes the username from the email verification and password reset process to prevent storing personally identifiable information (PII) in server and infrastructure logs. Customized HTML pages or emails related to email verification and password reset may need to be adapted accordingly. See the new templates that come bundled with Parse Server and the [migration guide](https://github.com/parse-community/parse-server/blob/alpha/8.0.0.md) for more details. ([d21dd97](d21dd97))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.0.0-alpha.13

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label Mar 2, 2025
parseplatformorg pushed a commit that referenced this pull request Mar 4, 2025
# [8.0.0](7.4.0...8.0.0) (2025-03-04)

### Bug Fixes

* LiveQueryServer crashes using cacheAdapter on disconnect from Redis 4 server ([#9616](#9616)) ([bbc6bd4](bbc6bd4))
* Push adapter not loading on some versions of Node 22 ([#9524](#9524)) ([ff7f671](ff7f671))
* Remove username from email verification and password reset process ([#8488](#8488)) ([d21dd97](d21dd97))
* Security upgrade node from 20.17.0-alpine3.20 to 20.18.2-alpine3.20 ([#9583](#9583)) ([8f85ae2](8f85ae2))

### Features

* Add dynamic master key by setting Parse Server option `masterKey` to a function ([#9582](#9582)) ([6f1d161](6f1d161))
* Add support for MongoDB `databaseOptions` keys `autoSelectFamily`, `autoSelectFamilyAttemptTimeout` ([#9579](#9579)) ([5966068](5966068))
* Add support for MongoDB `databaseOptions` keys `minPoolSize`, `connectTimeoutMS`, `socketTimeoutMS` ([#9522](#9522)) ([91618fe](91618fe))
* Add TypeScript support ([#9550](#9550)) ([59e46d0](59e46d0))
* Change default value of Parse Server option `encodeParseObjectInCloudFunction` to `true` ([#9527](#9527)) ([5c5ad69](5c5ad69))
* Deprecate `PublicAPIRouter` in favor of `PagesRouter` ([#9526](#9526)) ([7f66629](7f66629))
* Increase required minimum MongoDB versions to `6.0.19`, `7.0.16`, `8.0.4` ([#9531](#9531)) ([871e508](871e508))
* Increase required minimum Node versions to `18.20.4`, `20.18.0`, `22.12.0` ([#9521](#9521)) ([4e151cd](4e151cd))
* Increase required minimum versions to Postgres `15`, PostGIS `3.3` ([#9538](#9538)) ([89c9b54](89c9b54))
* Upgrade to express 5.0.1 ([#9530](#9530)) ([e0480df](e0480df))
* Upgrade to Parse JS SDK 6.0.0 ([#9624](#9624)) ([bf9db75](bf9db75))

### BREAKING CHANGES

* This upgrades the internally used Express framework from version 4 to 5, which may be a breaking change. If Parse Server is set up to be mounted on an Express application, we recommend to also use version 5 of the Express framework to avoid any compatibility issues. Note that even if there are no issues after upgrading, future releases of Parse Server may introduce issues if Parse Server internally relies on Express 5-specific features which are unsupported by the Express version on which it is mounted. See the Express [migration guide](https://expressjs.com/en/guide/migrating-5.html) and [release announcement](https://expressjs.com/2024/10/15/v5-release.html#breaking-changes) for more info. ([e0480df](e0480df))
* This upgrades to the Parse JS SDK 6.0.0. See the [change log](https://github.com/parse-community/Parse-SDK-JS/releases/tag/6.0.0) of the Parse JS SDK for breaking changes and more details. ([bf9db75](bf9db75))
* This removes the username from the email verification and password reset process to prevent storing personally identifiable information (PII) in server and infrastructure logs. Customized HTML pages or emails related to email verification and password reset may need to be adapted accordingly. See the new templates that come bundled with Parse Server and the [migration guide](https://github.com/parse-community/parse-server/blob/alpha/8.0.0.md) for more details. ([d21dd97](d21dd97))
* This releases increases the required minimum versions to Postgres `15`, PostGIS `3.3` and removes support for Postgres `13`, `14`, PostGIS `3.1`, `3.2`. ([89c9b54](89c9b54))
* The default value of Parse Server option `encodeParseObjectInCloudFunction` changes to `true`; the option has been deprecated and will be removed in a future version. ([5c5ad69](5c5ad69))
* This releases increases the required minimum MongoDB versions to `6.0.19`, `7.0.16`, `8.0.4` and removes support for MongoDB `4`, `5`. ([871e508](871e508))
* This releases increases the required minimum Node versions to 18.20.4, 20.18.0, 22.12.0 and removes unofficial support for Node 19. ([4e151cd](4e151cd))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state:breaking Breaking change requires major version increment and `BREAKING CHANGE` commit message state:released-alpha Released as alpha version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove username from password reset / email verification links
4 participants