feat(auth): add --webauthn browser step-up as an alternative to TOTP - #562
Draft
Matovidlo wants to merge 1 commit into
Draft
feat(auth): add --webauthn browser step-up as an alternative to TOTP#562Matovidlo wants to merge 1 commit into
Matovidlo wants to merge 1 commit into
Conversation
Adds a WebAuthn/passkey path for `auth pat-create`'s sudo step-up, per Zajca's suggestion: a passkey ceremony (navigator.credentials.get()) can only run on a page whose origin matches the credential's relying-party id (confirmed: it's bound to the login/MFA domain), so it cannot be completed by a page kbagent hosts itself on 127.0.0.1 -- the ceremony has to be served by the stack, mirroring how /admin/auth/pkce/authorize already works for `auth login`. This adds the CLI-side half of that pattern: - auth/webauthn_browser.py: a loopback callback server (closely mirroring pkce.py's) that opens a browser at the ceremony page and waits for the redirect back with the resulting assertion. - AuthClient.sudo_challenge / sudo_webauthn: POST /v1/auth/sudo/challenge and the webauthn branch of POST /v1/auth/sudo. - AuthService._perform_webauthn_sudo, mirroring _perform_pkce's shape. - `auth pat-create --webauthn`, mutually exclusive with --totp-code, and usable under --json/non-TTY (no typed code to prompt for). The exact browser-facing ceremony page path and its redirect-back query contract (AUTH_SUDO_WEBAUTHN_CEREMONY_PATH) are a documented placeholder -- confirmed with the platform team that redirects go back to localhost, same as PKCE, but the precise page/params still need confirming against a live stack before this is used for real. Everything else (the loopback listener, the challenge/assertion wiring, the CLI flag) does not change once that one constant is confirmed.
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.
Summary
Stacked on #561 (TOTP-only PAT support) -- this diff is exactly the
--webauthnaddition.--webauthntokbagent auth pat-create, mutually exclusive with--totp-code: opens a browser for a passkey ceremony instead of a typed TOTP code.auth/webauthn_browser.py(new): a loopback callback server mirroringauth/pkce.pyalmost exactly -- opens a browser at the (stack-hosted) ceremony page and waits for the redirect back with the resulting WebAuthn assertion.AuthClient.sudo_challenge/sudo_webauthn:POST /v1/auth/sudo/challengeand thewebauthnbranch ofPOST /v1/auth/sudo.AuthService._perform_webauthn_sudo, mirroring_perform_pkce's shape.Why this needed a browser at all
A WebAuthn ceremony (
navigator.credentials.get()) only runs on a page whose origin matches (or is a registrable suffix of) the credential's relying-party id -- confirmed this is bound to the actual login/MFA domain, not something kbagent could satisfy with a page it hosts itself on127.0.0.1. So this mirrors/admin/auth/pkce/authorize's existing pattern forauth login: the ceremony page has to be served by the stack; kbagent's job is only to open a browser there and receive the redirect-back result on a loopback listener.AUTH_SUDO_WEBAUTHN_CEREMONY_PATH(constants.py) is a documented placeholder -- the exact browser-facing ceremony page path and its redirect-back query parameter names (assertion,stateback;challengeToken,options,redirectUri,stateout) are this module's best guess at a page mirroring the PKCE authorize/callback contract, not a confirmed one. Everything else (the loopback listener, the challenge/assertion wiring intoPOST /v1/auth/sudo, the CLI flag) is real and does not change once the real page/contract is confirmed -- only that one constant (and possibly the query parameter names inwebauthn_browser.py'sbuild_ceremony_url) need adjusting.This PR is intentionally left in draft for live testing before it goes up for review -- see the commands below to point it at a real stack and iterate on the placeholder.
How to test against a live stack
Change type
Feature (follow-up to #561). No breaking changes.
Impact analysis
auth/webauthn_browser.py.auth/auth_client.py,auth/models.py,services/auth_service.py,commands/auth.py,constants.py-- no existing behavior changed.Test plan
test_auth_webauthn_browser.py(real loopback HTTP server -- success, state mismatch, ceremony denial, timeout, URL building),test_auth_client.py(sudo_challenge/sudo_webauthn),test_auth_service.py(webauthn-path ordering, sudo-failure, state-mismatch propagation),test_cli_auth.py(--webauthn/--totp-codemutual exclusion,--webauthnunder--json/non-TTY).make checkgreen end-to-end (5453 passed, 11 skipped, 0 failed).Deployment
Merge & automatic deploy, once the placeholder is confirmed. No migration.
Rollback plan
Revert of this PR (independent of #561).