passkey support - #29
Conversation
|
@code-hustler-ft3d can you please confirm this script works for your existing 2fa flow... (I am using passless to provide the passkey virtual device). I have confirmed that it works for me |
Builds on jpike88's passkey handling (PR #29) without altering its mechanics. Four additions: Opt-in gate. PASSKEY_AUTHENTICATE (default unset = off). With it unset, a passkey prompt in the Second Factor dialog still fails loudly, using the exact reason string v0.8.1 emits for the browser-window variant so existing monitors keep matching, now with a remediation= hint pointing at the flag. Every existing flow is byte-for-byte unchanged unless the operator opts in. Off by default because the maintainer has no passkey account to verify against; the contributor does, and uses it in production. Flow tests. tests/test_pure_logic.py drives the real handle_2fa with a mock agent in the configurations that matter: TOTP dialog with the gate on and off (code still typed, Authenticate never pressed), passkey dialog with and without a TOTP secret (Authenticate pressed, nothing typed), gate off on a passkey dialog (fails loud, touches nothing), and the IB Key push loop with a normal dialog (left alone, success via the API port) -- the path the issue #23 reporter and every IB Key user runs. Each asserts the handler was actually consulted rather than bypassed. Plus the pure helper and the env parsing. 13 new tests; 335 pass. Docs. README reframes the passkey paragraph from "not supported" to "the controller presses Authenticate, you supply the authenticator", marked as contributor-validated; OBSERVABILITY gains the new ALERT_2FA_FAILED reason and the env var; UPGRADING gets an entry. Changelog. The one-line entry was inside [0.9.0], which shipped on 2026-09-07; it moves to a new [Unreleased] section with a full entry crediting the contributor, including the latent IB Key bug the PR fixed in the post-relogin loop. Also a comment at the point where the handler returns True on an accepted click, spelling out that this reports 2FA success before the ceremony completes and that a never-answering authenticator surfaces as the API-port wait timing out.
|
Thanks — and to answer your question directly: yes, it leaves the existing 2FA flows intact. I didn't want to say that from reading alone, so I drove the real
Your full suite passes on that commit too (322). And the code is careful in ways I appreciated: no new agent commands, no coordinates, refusing an ambiguous multi-window match, re-reading the dialog before the raw-name retry, stripping CR/LF because the protocol is line-oriented. You also fixed a latent bug of ours — the post-relogin loop would have called the TOTP generator with an empty secret in IB Key mode. On scope: this is the arrangement I said in #22 I'd revisit if someone got an out-of-tree signer working. You did, with passless. Pressing Authenticate and leaving the ceremony to your authenticator is driving Gateway's dialog, not holding a key. I'm in. What I've added rather than ask you to do, on
Two ways to get those onto this PR — your call:
Then one thing only you can do: re-run your live passless login with |
Builds on jpike88's passkey handling (PR #29) without altering its mechanics. Four additions: Opt-in gate. PASSKEY_AUTHENTICATE (default unset = off). With it unset, a passkey prompt in the Second Factor dialog still fails loudly, using the exact reason string v0.8.1 emits for the browser-window variant so existing monitors keep matching, now with a remediation= hint pointing at the flag. Every existing flow is byte-for-byte unchanged unless the operator opts in. Off by default because the maintainer has no passkey account to verify against; the contributor does, and uses it in production. Flow tests. tests/test_pure_logic.py drives the real handle_2fa with a mock agent in the configurations that matter: TOTP dialog with the gate on and off (code still typed, Authenticate never pressed), passkey dialog with and without a TOTP secret (Authenticate pressed, nothing typed), gate off on a passkey dialog (fails loud, touches nothing), and the IB Key push loop with a normal dialog (left alone, success via the API port) -- the path the issue #23 reporter and every IB Key user runs. Each asserts the handler was actually consulted rather than bypassed. Plus the pure helper and the env parsing. 13 new tests; 335 pass. Docs. README reframes the passkey paragraph from "not supported" to "the controller presses Authenticate, you supply the authenticator", marked as contributor-validated; OBSERVABILITY gains the new ALERT_2FA_FAILED reason and the env var; UPGRADING gets an entry. Changelog. The one-line entry was inside [0.9.0], which shipped on 2026-09-07; it moves to a new [Unreleased] section with a full entry crediting the contributor, including the latent IB Key bug the PR fixed in the post-relogin loop. Also a comment at the point where the handler returns True on an accepted click, spelling out that this reports 2FA success before the ceremony completes and that a never-answering authenticator surfaces as the API-port wait timing out.
…ler-ft3d#29 Builds on jpike88's passkey handling (PR code-hustler-ft3d#29) without altering its mechanics. Four additions: Opt-in gate. PASSKEY_AUTHENTICATE (default unset = off). With it unset, a passkey prompt in the Second Factor dialog still fails loudly, using the exact reason string v0.8.1 emits for the browser-window variant so existing monitors keep matching, now with a remediation= hint pointing at the flag. Every existing flow is byte-for-byte unchanged unless the operator opts in. Off by default because the maintainer has no passkey account to verify against; the contributor does, and uses it in production. Flow tests. tests/test_pure_logic.py drives the real handle_2fa with a mock agent in the configurations that matter: TOTP dialog with the gate on and off (code still typed, Authenticate never pressed), passkey dialog with and without a TOTP secret (Authenticate pressed, nothing typed), gate off on a passkey dialog (fails loud, touches nothing), and the IB Key push loop with a normal dialog (left alone, success via the API port) -- the path the issue code-hustler-ft3d#23 reporter and every IB Key user runs. Each asserts the handler was actually consulted rather than bypassed. Plus the pure helper and the env parsing. 13 new tests; 335 pass. Docs. README reframes the passkey paragraph from "not supported" to "the controller presses Authenticate, you supply the authenticator", marked as contributor-validated; OBSERVABILITY gains the new ALERT_2FA_FAILED reason and the env var; UPGRADING gets an entry. Changelog. The one-line entry was inside [0.9.0], which shipped on 2026-09-07; it moves to a new [Unreleased] section with a full entry crediting the contributor, including the latent IB Key bug the PR fixed in the post-relogin loop. Also a comment at the point where the handler returns True on an accepted click, spelling out that this reports 2FA success before the ceremony completes and that a never-answering authenticator surfaces as the API-port wait timing out.
|
I have updated my branch as requested, and I have tested the update to date branch with the PASSKEY_AUTHENTICATE=yes flag present, and it appears to work fine :) |
|
Merged — thank you. Before merging I checked that your branch is byte-identical to the one I tested, and the full suite passes on your exact commit (352). It's on main with the gate, tests and docs, and ships in the next release. Your live run with If a Gateway update or a passless change stops the prompt from matching, the signal will be |
#30, #32 and #34 each change what an operator sees, and none of them added the docs/UPGRADING.md entry the PR checklist asks for: - #30 adds ALERT_CONFIG_NOT_APPLIED, an ERROR-level token worth paging on, and a few seconds to the post-login config pass. - #32 makes a mis-shaped TWOFACTOR_CODE exit with status 2 at startup instead of crashing with a traceback at the 2FA dialog after a full login. - #34 changes device-list matching and its log output, and only takes effect from a new image because it lives in the agent jar. Entries go under the existing Unreleased heading alongside #29's.
…, config and secret checks Cuts 0.10.0 from what landed since v0.9.0: - #29 (@jpike88): press Authenticate on Gateway's passkey prompt, opt-in via PASSKEY_AUTHENTICATE; an authenticator running alongside the container completes the WebAuthn ceremony. - #34 (fixes #33, reported by @ldicarlo): the 2FA device selector no longer fails on a difference in case or spacing, and a miss lists the entries. Agent change. - #32: a mis-shaped TWOFACTOR_CODE stops the controller at startup instead of crashing at the 2FA dialog after a full login. - #30: a Lock and Exit schedule Gateway drops is reported with ALERT_CONFIG_NOT_APPLIED instead of being claimed as applied. - #31: the README documents the attended VNC fallback. Minor rather than patch: #29 adds a feature and an env var. Release prep: - version 0.9.0 -> 0.10.0 in the controller and Makefile; - CHANGELOG [Unreleased] -> [0.10.0] - 2026-09-14, and UPGRADING Unreleased -> v0.10.0; - OBSERVABILITY said ALERT_CONFIG_NOT_APPLIED arrived "in v0.9.1", a version that will never exist, and dated several additions by PR or issue number; all now follow the file's "Added vX.Y.Z" convention; - the README env table gains the PASSKEY_AUTHENTICATE row it lacked; - ci.yml gains workflow_dispatch. GitHub created no CI run for the push of #34's merge commit (8cadf39): no check suite at all, and no skip directive, path filter or concurrency setting to explain it. There was no way to start one by hand. Every release step is conditioned on a tag ref, so a dispatch on a branch builds and tests without publishing.
…, config and secret checks (#35) - Passkey (#29): with PASSKEY_AUTHENTICATE=yes the controller presses Authenticate on Gateway's passkey prompt, and an authenticator running next to the container completes WebAuthn. Off by default. - 2FA device selector (#34, fixes #33): an exact TWOFA_DEVICE match wins, otherwise the one entry matching without regard to case, spacing or HTML is picked. A miss logs the entries. Agent change, so it needs the new image. - TWOFACTOR_CODE (#32): a value that isn't a base32 secret exits with status 2 at startup. - Lock and Exit (#30): the schedule is read back after it is applied, and a dropped value raises ALERT_CONFIG_NOT_APPLIED. - README (#31): finishing 2FA by hand over VNC. - ci.yml: manual runs via workflow_dispatch. Only tags publish.
What this PR does
This PR adds support for passkey dialog flow detection. It just presses authenticate, and leaves the user to use their passkey authentication, which on success will log the user in.
Checklist
make clean && make && make testpasses (full unit suite green)docs/OBSERVABILITY.mdupdated (if touching ALERT tokens,/health, or env vars listed there)docs/FROM_IBC.mdupdated (if changing anything that maps to an IBC key)docs/UPGRADING.mdgets a new### vX.Y.Zsection if the change is operator-visibleSee
CONTRIBUTING.mdfor the"Adding a new..." walkthroughs covering the most common extension
points (ALERT tokens, dialog handlers, env vars, IBC-key mappings).