diff --git a/PHASE5_RUNBOOK.md b/PHASE5_RUNBOOK.md index ede6b07..d5f4446 100644 --- a/PHASE5_RUNBOOK.md +++ b/PHASE5_RUNBOOK.md @@ -8,6 +8,8 @@ Related browser demo: - `k_client_portal.py` can now be used in `k_client` at `http://127.0.0.1:8766` to show: - registration + - current registered-user list from `k_proxy` + - unregister from the browser page - login with card approval/denial - protected `k_server` counter access - logout @@ -218,7 +220,7 @@ Verified result on 2026-04-25: - next step is to recover the USB/Qubes transport path before retrying direct auth - after a full power cycle and reattach, manual CTAPHID `INIT` replies again and `webauthn_local_demo.py` registration succeeds again - direct `raw_ctap_probe.py --device-path /dev/hidraw0 make-credential --rp-id localhost` also succeeds again after pressing `yes` on the card - - `k_proxy_app.py --auth-mode fido2-direct` was patched to use low-level CTAP2 and explicit `/dev/hidraw0` + - `k_proxy_app.py --auth-mode fido2-direct` was patched to use low-level CTAP2 and to auto-detect the working `/dev/hidraw*` node when the card re-enumerates - after additional fixes for hidraw lifetime, VM-side `python-fido2` response mapping, and CTAP payload shape, `/enroll/register` now succeeds again for `directtest` - `/session/login` for `directtest` now also succeeds after card confirmation and returns `auth_mode: "fido2_assertion"` - `/session/status` succeeds diff --git a/Setup.md b/Setup.md index b3f79f3..80d938b 100644 --- a/Setup.md +++ b/Setup.md @@ -366,6 +366,11 @@ Session note (2026-04-25, k_client browser flow page): - login with card approval or denial in `k_proxy` - call the protected `k_server` counter - logout +- The page now also exposes current proxy enrollment state: + - shows the registered users visible in `k_proxy` + - lets the operator select a listed user into the username field + - lets the operator unregister users from the browser page + - login now uses the current username field instead of only the portal's last remembered user - It also makes the negative path explicit: - if login is denied on the card, the page reports that `k_server` was not called - Primary browser-facing app logic still lives on `k_proxy`, but the `k_client` page is now a concrete demo/control surface rather than just a redirect. @@ -586,6 +591,9 @@ Session note (2026-04-25, direct FIDO2 auth attempt): - protected `/resource/counter` access succeeds again through `k_proxy -> k_server` - logout succeeds - post-logout protected access returns `401` + - direct mode no longer depends on a fixed `/dev/hidraw0` path + - after a later re-enumeration where the card appeared on `/dev/hidraw1`, `k_proxy_app.py` was patched to probe available `/dev/hidraw*` nodes and select the first working CTAPHID device automatically + - browser registration then worked again without changing the configured `--direct-device-path` - temporary direct-mode hidraw lifetime logging has been removed again after diagnosis - `/home/user/chromecard/phase5_chain_regression.sh` now supports the direct-auth baseline via: - `--interactive-card` diff --git a/Workplan.md b/Workplan.md index 6dd0fc7..8be6eef 100644 --- a/Workplan.md +++ b/Workplan.md @@ -258,7 +258,7 @@ Status (2026-04-25): - rerunning `webauthn_local_demo.py` inside `k_proxy` also still gives no card prompt, so the current break is below both browser WebAuthn and direct host probes - after a full power cycle and reattach, manual CTAPHID `INIT` replies again and browser registration in `webauthn_local_demo.py` succeeds again - direct `raw_ctap_probe.py --device-path /dev/hidraw0 make-credential --rp-id localhost` now also succeeds again after card confirmation - - `k_proxy_app.py --auth-mode fido2-direct` has been moved onto low-level CTAP2 and explicit `/dev/hidraw0` + - `k_proxy_app.py --auth-mode fido2-direct` has been moved onto low-level CTAP2 with hidraw auto-detection; it still accepts `--direct-device-path`, but no longer breaks if the card re-enumerates onto `/dev/hidraw1` - after repeated fixes for hidraw lifetime, VM-side `python-fido2` response mapping, and CTAP payload shape, real app registration now succeeds for `directtest` ## Phase 5.5: Implement Dummy Resource + Access Policy on `k_server` @@ -321,6 +321,9 @@ Status (2026-04-25): - browser now targets `k_proxy` directly over `https://127.0.0.1:9771` - `k_client_portal.py` also serves a local browser flow page on `http://127.0.0.1:8766` - `k_proxy` continues to authenticate with the card and forward to `k_server` + - the `k_client` page now also lists registered users from `k_proxy` + - the `k_client` page can unregister users from the browser + - the portal login action now uses the current username field instead of only the remembered local user - Verified end-to-end through the portal: - enroll `alice` - login succeeds diff --git a/k_client_portal.py b/k_client_portal.py index df8cbee..82f4b13 100644 --- a/k_client_portal.py +++ b/k_client_portal.py @@ -146,6 +146,41 @@ HTML = """ font-size: 0.95rem; color: var(--muted); } + #usersList { + display: grid; + gap: 8px; + margin-top: 12px; + } + .user-row { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + gap: 10px; + padding: 10px 12px; + border: 1px solid var(--line); + background: rgba(255,255,255,0.86); + } + .user-meta { + display: grid; + gap: 2px; + } + .user-name { + font-weight: 600; + } + .user-subtle { + color: var(--muted); + font-size: 0.9rem; + } + .user-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + .small { + padding: 8px 10px; + font-size: 0.92rem; + } .badge { display: inline-block; padding: 4px 8px; @@ -277,6 +312,11 @@ HTML = """