feat(auth): bootstrap aw-webui token on launch#216
feat(auth): bootstrap aw-webui token on launch#216ErikBjare merged 1 commit intoActivityWatch:masterfrom
Conversation
Greptile SummaryThis PR bootstraps the aw-webui authentication credential into the Tauri dashboard URL on launch and bumps The implementation is clean and well-tested. Two P2 findings are worth a quick cross-repo check with aw-webui#806 before shipping to production users: Confidence Score: 5/5Safe to merge; all findings are P2 quality/security-hygiene suggestions that do not block correctness. The core logic is straightforward and correct: the credential is only appended when non-empty, the URL crate handles encoding properly, and three targeted unit tests cover all meaningful code paths. The two P2 findings (credential in Rocket access log; encoding assumption) are informational and depend on aw-webui behavior outside this PR. No P0/P1 issues were found. No files require special attention beyond the P2 observations noted inline on src-tauri/src/lib.rs.
|
| Filename | Overview |
|---|---|
| src-tauri/src/lib.rs | Adds build_dashboard_url helper that appends a token query param when auth is configured, plus three focused unit tests; the credential is not logged in plaintext but does appear in the Rocket HTTP access log as a query parameter on the initial page load. |
| src-tauri/Cargo.lock | Bumps all aw-server-rust crates to the auth-aware commit, adds subtle (constant-time comparison) as a new transitive dependency, and consolidates duplicate windows-core versions. |
Sequence Diagram
sequenceDiagram
participant T as aw-tauri (run)
participant C as aw-server config
participant B as build_dashboard_url
participant W as Tauri WebviewWindow
participant S as aw-server Rocket
participant UI as aw-webui SPA
T->>C: create_config(testing)
C-->>T: aw_config with auth field
T->>T: extract credential, filter empty
T->>B: build_dashboard_url(port, credential)
alt credential is non-empty
B->>B: append query param via query_pairs_mut
end
B-->>T: dashboard_url
T->>S: async spawn Rocket server
T->>W: WebviewUrl::External(dashboard_url)
W->>S: GET with credential in query string (written to access log)
S-->>UI: serve SPA
UI->>UI: read credential via URLSearchParams
UI->>UI: history.replaceState to clean URL
UI->>S: subsequent API calls with stored credential
Reviews (1): Last reviewed commit: "feat(auth): bootstrap aw-webui token on ..." | Re-trigger Greptile
| fn build_dashboard_url(port: u16, api_key: Option<&str>) -> Url { | ||
| let mut url = | ||
| Url::parse(&format!("http://localhost:{port}/")).expect("Failed to parse localhost url"); | ||
|
|
||
| if let Some(api_key) = api_key.filter(|key| !key.is_empty()) { | ||
| url.query_pairs_mut().append_pair("token", api_key); | ||
| } | ||
|
|
||
| url | ||
| } |
There was a problem hiding this comment.
Auth credential visible in Rocket access log
Because the credential is passed as a URL query parameter, Rocket will write the full request line — including the token value — to its HTTP access log on every app launch. On a shared or multi-user machine, log files often carry broader read permissions than the config file from which the credential is read, slightly widening the exposure surface.
A common mitigation is for the webui to call history.replaceState to strip the token from the address bar immediately after reading it, so subsequent navigation logs contain only the clean URL. Worth confirming this cleanup is handled in ActivityWatch/aw-webui#806.
| #[test] | ||
| fn build_dashboard_url_appends_encoded_token() { | ||
| assert_eq!( | ||
| build_dashboard_url(5600, Some("secret+ /?=&")).as_str(), | ||
| "http://localhost:5600/?token=secret%2B+%2F%3F%3D%26" | ||
| ); | ||
| } |
There was a problem hiding this comment.
query_pairs_mut().append_pair() uses application/x-www-form-urlencoded encoding, so space becomes + in the serialized URL. URLSearchParams in JavaScript correctly decodes + → space, so the round-trip is fine if aw-webui uses new URLSearchParams(location.search).get('token'). However, if it uses decodeURIComponent() (which treats + as a literal plus sign), any credential containing a space would be silently corrupted.
This is mainly a cross-repo concern to confirm with ActivityWatch/aw-webui#806, but it's worth adding a comment above the test noting the +-for-space convention so future readers don't mistake the expected value for a bug.
|
Cross-checked the two Greptile P2 notes against ActivityWatch/aw-webui#806: that PR reads the token via URL parsing, stores it in sessionStorage, and strips it from the address bar after bootstrap, so the launch URL cleanup/decoding path is covered on the webui side. CI is green and GitHub reports this branch as CLEAN/MERGEABLE. I attempted to merge it from this account, but TimeToBuildBob does not have MergePullRequest permission in ActivityWatch/aw-tauri, so this is ready for a maintainer merge. |
|
I was testing this, should have left a comment ,sorry. It doesn't seem to work for me, the tauri window is blank whenever I add an apikey to the aw-server-rust config.toml. Will investigate and try pushing a fix. @ErikBjare does it work on your machine? |
|
I have not yet tested it, I didn't assume it was working yet as it needs ActivityWatch/aw-webui#806 which I just merged. Easier to debug once basics are merged and it should work than debug a cross-repo PRs, heh. @TimeToBuildBob Something we are missing or did you expect it to work? Would be cool if you could try the computer use user-testing for this (I'd suggest with |

Summary
aw-server-rustinCargo.lockto the auth-aware revision?token=...to the initial dashboard URL when[auth].api_keyis configuredThis is the
aw-taurileg of the ActivityWatch API auth rollout.Related:
Verification
cargo fmt --manifest-path src-tauri/Cargo.tomlprek run fmt --files src-tauri/src/lib.rsprek run end-of-file-fixer --files src-tauri/Cargo.lock src-tauri/src/lib.rsprek run check-added-large-files --files src-tauri/Cargo.lock src-tauri/src/lib.rscargo test --manifest-path src-tauri/Cargo.toml build_dashboard_url --lib(blocked locally: this machine is missinggdk-3.0dev libraries, so Tauri/GTK deps fail before the crate compiles)