mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
fix(auth): a new email address on an account with a second factor needs that factor
The address is what single sign-on links an existing account by, and changing it took the password or a session younger than five minutes on every account. A remembered browser skips the second factor at sign-in and still makes a fresh session, so the password alone could move the address of an account the second factor was meant to protect. On an account with a second factor only a second factor or passkey completed in the last five minutes counts now; the password is not checked. The refusal names it (second_factor_required in rejectedFields, or 401 profile.update.emailSecondFactorRequired when the address was all that changed), and the profile form opens the re-proof dialog with the factors the account holds, then saves again, no longer offering the password field. Accounts without a second factor keep the password or a recent sign-in. A token cannot change the address of such an account; the app does not change it.
This commit is contained in:
1 parent
bd270d635a
commit
9642c749c9
16 files changed
+280
-61
No files matched your search
@@ -290,6 +290,7 @@ export const ERROR_CODE_CATALOGUE: Readonly<Record<string, readonly string[]>> =
|
||||
profile: [
|
||||
"profile.update.emailInUse",
|
||||
"profile.update.emailRateLimited",
|
||||
"profile.update.emailSecondFactorRequired",
|
||||
"profile.update.invalidBody",
|
||||
"profile.update.nothingSaved",
|
||||
],
|
||||
|
||||
@@ -487,7 +487,7 @@ export const profileUpdateRequest = z
|
||||
.max(512)
|
||||
.optional()
|
||||
.describe(
|
||||
"The account password, sent only alongside a NEW `email`. Moving the account to a new address needs a fresh proof because single sign-on links an existing account by it: a browser session that signed in or completed a second factor in the last five minutes needs nothing more, otherwise this field must carry the current password. Without an accepted proof the address is not changed and comes back in `rejectedFields` as `reproof_required` or `reproof_failed` (or, when the address was the only field sent, 401 `auth.reproof.required` / `auth.reproof.failed`). Attempts draw on the account's shared re-proof budget of five per fifteen minutes. Never stored.",
|
||||
"The account password, sent only alongside a NEW `email`. Moving the account to a new address needs a fresh proof because single sign-on links an existing account by it: a browser session that signed in or completed a second factor in the last five minutes needs nothing more, otherwise this field must carry the current password. Without an accepted proof the address is not changed and comes back in `rejectedFields` as `reproof_required` or `reproof_failed` (or, when the address was the only field sent, 401 `auth.reproof.required` / `auth.reproof.failed`). On an account with a second factor the password is not accepted and not checked: only a second factor or passkey completed in the last five minutes counts (at sign-in or at POST /api/auth/reproof), and without one the address comes back as `second_factor_required` (or 401 `profile.update.emailSecondFactorRequired` when it was the only field). A token cannot change the address of such an account. Attempts draw on the account's shared re-proof budget of five per fifteen minutes. Never stored.",
|
||||
),
|
||||
})
|
||||
.meta({
|
||||
|
||||
Reference in new issue
Block a user