Repository navigation
fix(auth): ask for the authenticator code on sign-in when 2FA is on - #1456
Merged
Merged
Conversation
Both React apps let users enable two-factor authentication, but neither login page could send the code, so every later sign-in failed with 401 two_factor_required and locked the user out. When POST /token/issue answers with the ProblemDetails code Identity.TwoFactorRequired, the admin and dashboard login cards now switch to a six-digit code step (one-time-code autocomplete, numeric input) and repeat the call with twoFactorCode. A wrong code (Identity.TwoFactorInvalid) shows an inline error and keeps the user on the step; Back returns to the password step. The password is held only in component state for the retry and is cleared on back, success and unmount. The integration test exception handler now mirrors the production handler's code extension, and the 2FA login tests assert both codes, since the clients depend on them. Closes #1446
… step Resolve the login page conflicts against main's i18n work: keep main's translated form, notice banner and demo accounts, and re-apply the authenticator code step on top. The TwoFactorStep strings and the invalid-code error now come from the auth catalog (en-US + pt-BR) in both apps.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Both React apps let a user turn on two-factor authentication under Settings > Security, but neither login page ever sent the authenticator code. After enabling 2FA, every sign-in failed with
401 two_factor_required, the form showed a generic error, and the user was locked out of the app that offered the feature.Fix
The API already supported the second factor and already tags the 401 with a stable ProblemDetails
code(Identity.TwoFactorRequiredfor a missing code,Identity.TwoFactorInvalidfor a wrong one), so no API change was needed. The clients branch on that code, not on thedetailtext, which is localized.In both
clients/adminandclients/dashboard:issueTokenandloginaccept an optionaltwoFactorCode, sent only when present.Identity.TwoFactorRequired, the login card switches to a code step: a six-digit field (autocomplete="one-time-code",inputmode="numeric", autofocus), a Verify button and a "Back to sign in" link. The page repeats the call with email, password, tenant andtwoFactorCode.localStorageorsessionStorage.tenantheader.All new strings (the code step's heading, label, placeholder, buttons, back link and the wrong-code error) come from the
authcatalog in both locales, en-US and pt-BR, so the step follows the language switcher like the rest of the login page.Both login pages already use controlled inputs (admin's login doesn't use react-hook-form), so the new step follows the same approach. Recovery codes aren't supported by the API (
VerifyTwoFactorOrThrowAsynconly checks the authenticator provider), so the step accepts authenticator codes only.On the backend side this is test-only: the integration-test exception handler now mirrors the production handler's
codeextension, and the two existing 2FA login tests assert both codes, since the clients now depend on them.Tests
tests/auth/two-factor-login.spec.tsin each app (4 tests each): 2FA user gets the code step and signs in with the second call carryingtwoFactorCode(and the password never lands in browser storage); a wrong code shows the error and stays on the step; Back returns to the password step with the password cleared; a non-2FA user still signs in in one step.i18n/switcher.spec.tsimpersonation case andsystem/tenant-deactivated.spec.tsunrelated-403 case, bothwaitForLoadStatetimeouts).TwoFactorAuthTests, 6/6).eslint .(0 errors, including the i18next literal-string rule) andtsc -b --noEmitclean in both apps.Docs: fullstackhero/docs#276 (changelog entry, new "Signing in from the React apps" section on the two-factor page, and a correction: the page said clients key off the detail prefixes).
Closes #1446
Thanks @marcelo-maciel for the detailed report.