authhelper: support single-input TOTP fields and improve field interaction#7259
authhelper: support single-input TOTP fields and improve field interaction#7259sarathivengadesh wants to merge 3 commits intozaproxy:mainfrom
Conversation
…nteraction - Add TOTP_FIELD support for single combined input (e.g. GitHub, Codeberg style) in addition to existing per-character input boxes - Replace fillField with fillFieldWithEvents to trigger JS events so React/Angular apps register typed values correctly - Add precomputedTotpCode overload to avoid clock skew across multiple steps - Fix MsLoginAuthenticator to use updated DefaultAuthenticator signature Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
All contributors have signed the CLA ✍️ ✅ |
|
Great job! No new security vulnerabilities introduced in this pull requestUse @Checkmarx to interact with Checkmarx PR Assistant. |
|
I have read the CLA Document and I hereby sign the CLA |
|
This needs tests. |
|
Also examples where the current sendKeys fails, that sounds more like a bug in the WebDriver spec since they are supposed to behave like user input. |
|
@thc202 Thanks for the feedback! To clarify, there are two separate issues addressed in this PR:
|
|
I understand what the PR is attempting to do. |
…add tests - Revert MsLoginAuthenticator PROOF_TOTP handling back to original clear()+sendKeys() as the existing code was working correctly - Add AuthenticationStepUnitTest covering split-TOTP charIndex logic, single combined field path, precomputed code, and TotpSupport fallback - Add FillFieldWithEventsTest in AuthUtilsUnitTest covering fill, clear-before-fill, JS event dispatch, and non-JS driver robustness - Fix DefaultAuthenticator: remove unnecessary .toString() on String return
4a9bd06 to
d7dd821
Compare
|
#7259 (comment) |
|
It's not necessary to ask for a review, I get notifications of all comments and pushes. |
| // Pre-generate TOTP code once so all 6 character fields use the same code, | ||
| // avoiding clock-window drift if a 30s boundary crosses during step execution. | ||
| String precomputedTotpCode = | ||
| splitTotpFields ? TotpSupport.getCode(credentials) : null; |
There was a problem hiding this comment.
This should be generated when needed not beforehand, the code will be outdated if the steps before the TOTP_FIELD step take more time than the defined period. This also fails to validate the required number of digits.
The change itself is also out of place, this breaks the step implementation isolation, better to provide a state object for the steps than add ad-hoc step specific logic here.
There was a problem hiding this comment.
Addressed. Added AuthenticationContext — a state object created once per authentication attempt and passed to every step. The TOTP code is now generated lazily at the moment the first TOTP_FIELD step executes (not before all steps run), so it stays fresh even if preceding steps take time. All TOTP logic remains inside AuthenticationStep; DefaultAuthenticator has no step-specific knowledge.
| } | ||
|
|
||
| @Nested | ||
| class FillFieldWithEventsTest { |
There was a problem hiding this comment.
These tests are not testing anything (you can change the script and the tests still pass). Please, add proper tests in BrowserTest.
|
#7259 (comment) |
For those cases which we can detect how many digits the field supports we should fill each field automatically instead of requiring the user to split the TOTP into several steps. |
…ct split OTP fields, browser tests - Add AuthenticationContext to lazily generate and cache the TOTP code at the moment the first TOTP_FIELD step executes, avoiding stale codes when preceding steps cross a 30-second window boundary - Remove pre-computation of TOTP code from DefaultAuthenticator; all step execution now goes through step.execute(wd, credentials, ctx) - Auto-detect split single-character OTP input boxes at runtime: if the resolved TOTP_FIELD element has maxlength="1", AuthUtils.fillSplitOtpFields locates all sibling inputs via JS and fills each with one digit — no need to configure multiple TOTP_FIELD steps - Replace mock-only FillFieldWithEventsTest (which did not verify script content) with two real BrowserTest methods: one that confirms input/change events fire on a React-style listener, and one that confirms split OTP boxes are auto-filled in DOM order - Update AuthenticationStepUnitTest for the new context-based API
8d1aeb2 to
08da194
Compare
|
The concrete reproduction case is app.dev.accuknox.com — its OTP screen uses React-controlled input[maxlength="1"] boxes. Plain sendKeys writes to the raw DOM but React's internal state never updates because React listens to synthetic events, not native DOM mutations. As a result the Submit button stays disabled and the form submits React's last known (empty) value. Dispatching an explicit input event after sendKeys triggers React's onChange handler, syncs the component state, and authentication succeeds. This was verified against that app. |
|
#7259 (comment) |
|
@sarathivengadesh could you create an example test app for this in the dev add-on? |
|
Can you share test credentials (or sample page)? I'd like to verify the behaviour. |

Overview
Changes: