You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(auth): re-auth identity guard — verify the account that signs back in
A 'Needs re-authentication' account sent the user to /login, but the login
surface let them authenticate as ANY identity (e.g. 'Sign in with Google' →
a different Google account). Nothing checked the result, the dead entry was
pruned up-front, and the ceremony silently completed as the wrong identity.
Now re-auth is identity-scoped end to end:
- reauthRedirect records the account being re-authenticated in a short-lived,
signed reauth-intent cookie (mirrors the last-used-login cookie) and KEEPS
the dead entry until re-auth actually succeeds (no up-front prune).
- Soft block (IdP): startIdpIntent appends login_hint=<loginName> to the
authorize URL so Google/OIDC pre-select that account (GitHub & others ignore
the unknown param — best-effort only).
- Hard block (our area): both completion points verify the authenticated
identity matches the intent —
• IdP callback (signInWithIdpIntent): compares the IdP-vouched loginName.
• password step: compares the typed loginName.
On MISMATCH: keep BOTH accounts and bounce to /accounts?reauthMismatch=1
(carrying the live requestId) with an explanatory banner — never silently
continue the ceremony as the unintended identity. On MATCH: continue and
prune the stale entry. The intent cookie is cleared either way.
- resolveIdentifier supersedes a prior same-identity (loginName+org) entry so a
password re-auth doesn't leave the kept dead entry shadowing the fresh one.
Tests: IdP guard (none/match/mismatch), login_hint append/omit, reauth-intent
cookie set + no prune, and the /accounts mismatch banner.
@@ -530,13 +530,13 @@ msgstr "Set up security key"
530
530
msgid"Set up SMS one-time code"
531
531
msgstr"Set up SMS one-time code"
532
532
533
-
#:app/routes/login/password.tsx:166
533
+
#:app/routes/login/password.tsx:182
534
534
#:app/routes/signup/index.tsx:286
535
535
#:app/routes/sso/ldap.tsx:82
536
536
msgid"Sign in"
537
537
msgstr"Sign in"
538
538
539
-
#:app/routes/login/password.tsx:155
539
+
#:app/routes/login/password.tsx:171
540
540
#:app/routes/logout/success.tsx:22
541
541
#:app/utils/errors/auth-error-recovery.tsx:47
542
542
msgid"Sign in again"
@@ -561,7 +561,7 @@ msgstr "Sign in with LDAP"
561
561
msgid"Sign out"
562
562
msgstr"Sign out"
563
563
564
-
#:app/routes/login/index.tsx:348
564
+
#:app/routes/login/index.tsx:353
565
565
msgid"Sign-in is currently unavailable for this account. Please contact your administrator."
566
566
msgstr"Sign-in is currently unavailable for this account. Please contact your administrator."
567
567
@@ -683,7 +683,7 @@ msgstr "Use your passkey to verify your identity."
683
683
msgid"Use your security key to verify your identity."
684
684
msgstr"Use your security key to verify your identity."
685
685
686
-
#:app/routes/login/index.tsx:208
686
+
#:app/routes/login/index.tsx:213
687
687
#:app/routes/sso/ldap.tsx:73
688
688
msgid"Username"
689
689
msgstr"Username"
@@ -757,7 +757,7 @@ msgstr "We've sent a password reset link to <0>{0}</0>"
757
757
msgid"We've sent a verification link to <0>{0}</0>"
758
758
msgstr"We've sent a verification link to <0>{0}</0>"
759
759
760
-
#:app/routes/login/index.tsx:245
760
+
#:app/routes/login/index.tsx:250
761
761
msgid"Welcome"
762
762
msgstr"Welcome"
763
763
@@ -795,6 +795,10 @@ msgstr "You may return to your device."
795
795
msgid"You must be signed in to link an external account."
796
796
msgstr"You must be signed in to link an external account."
797
797
798
+
#:app/routes/accounts.tsx:98
799
+
msgid"You signed in as a different account than the one you were re-authenticating. Both are kept — choose an account to continue."
800
+
msgstr"You signed in as a different account than the one you were re-authenticating. Both are kept — choose an account to continue."
801
+
798
802
#:app/routes/device/authorize.tsx:134
799
803
msgid"You'll be asked to sign in before authorizing."
800
804
msgstr"You'll be asked to sign in before authorizing."
@@ -811,7 +815,7 @@ msgstr "You're almost done! <0>{loginName}</0>"
811
815
msgid"You've been signed out"
812
816
msgstr"You've been signed out"
813
817
814
-
#:app/routes/login/password.tsx:137
818
+
#:app/routes/login/password.tsx:153
815
819
msgid"Your account is temporarily locked after too many attempts."
816
820
msgstr"Your account is temporarily locked after too many attempts."
817
821
@@ -835,7 +839,7 @@ msgstr "Your password has expired. Please reset it to continue."
835
839
msgid"Your session has ended and you've been securely signed out of Datum. You can safely close this tab, or sign back in any time to pick up where you left off."
836
840
msgstr"Your session has ended and you've been securely signed out of Datum. You can safely close this tab, or sign back in any time to pick up where you left off."
0 commit comments