feat(vault): interactive TOTP two-factor auth#21
Merged
Merged
Conversation
A 2FA-enabled account no longer dead-ends on the password grant: on TwoFactorRequired, prompt for the authenticator code and resubmit. - vault-api: login_password gains two_factor: Option<&TwoFactor>; appends twoFactorToken/Provider/Remember (a wrong code re-challenges). - vault-ipc: TwoFactorCode + serde-defaulted two_factor on Request::Unlock. - vault-agent: threads it into the password grant (provider 0 = authenticator). - vault-cli: login/unlock resubmit on a challenge, reading the code from the controlling terminal (/dev/tty) so it works with the password piped to stdin; --totp / $BW_TOTP for non-interactive use. - vault-tui: an "Authenticator code" unlock step (stash password, resubmit with the code; Tab disabled mid-2FA). Scope: authenticator/TOTP provider only; other providers and "remember this device" are future work. An API key still bypasses 2FA entirely. Tests: vault-api wiremock challenge→resubmit; vault-ipc transport round-trip; vault-tui begin_2fa + request-with-code units. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
What
A 2FA-enabled account is no longer a dead end on the password grant. On
Error::TwoFactorRequired, Vault now prompts for the authenticator (TOTP)code and resubmits the token grant with it — the non-API-key 2FA path.
How
vault-api:login_passwordgainstwo_factor: Option<&TwoFactor>andappends
twoFactorToken/twoFactorProvider/twoFactorRemember. A wrong codere-challenges, so callers can re-prompt.
vault-ipc:TwoFactorCode+ serde-defaultedtwo_factoronRequest::Unlock(forward-compatible, likeapi_key/device_id).vault-agent: threads it into the password grant as provider0(authenticator). The api-key / persisted-key branches ignore it (not
2FA-challenged).
vault-cli:vault login/unlockresubmit on a challenge, reading thecode from the controlling terminal (
/dev/tty) — necessary becauseread_passwordconsumes stdin to EOF (the doc'dpass/gpgpiping).--totp/
$BW_TOTPsupply it non-interactively. An empty line aborts.vault-tui: an "Authenticator code" step in the unlock screen — stashesthe typed password, resubmits with the code;
Tab(PIN toggle) is inertmid-2FA.
Scope
Authenticator/TOTP provider only. Other providers (email, Duo, WebAuthn) and
"remember this device" are tracked follow-ups. An API key still bypasses 2FA
entirely (
docs/apikey.mdcross-references both paths).Tests
vault-api: wiremock challenge → coded resubmit → token (up_to_n_times(1)on the challenge mock so the retry falls through to success).
vault-ipc:Unlock.two_factortransport round-trip + absent-decodes-None.vault-tui:begin_2fastashes the password and clears the field; thefollow-up
request()carries the stashed password + the code;Tabstaysinert mid-2FA.
Local CI-exact gates all green:
fmt, fresh isolatedclippy -D warnings,cargo test --workspace --all-targetsunderRUSTFLAGS=-D warnings,cargo deny check(no new deps), both headless builds.🤖 Generated with Claude Code