Skip to content

feat(auth): bootstrap aw-webui token on launch#216

Merged
ErikBjare merged 1 commit intoActivityWatch:masterfrom
TimeToBuildBob:feat/auth-bootstrap-token
Apr 20, 2026
Merged

feat(auth): bootstrap aw-webui token on launch#216
ErikBjare merged 1 commit intoActivityWatch:masterfrom
TimeToBuildBob:feat/auth-bootstrap-token

Conversation

@TimeToBuildBob
Copy link
Copy Markdown
Contributor

Summary

  • bump aw-server-rust in Cargo.lock to the auth-aware revision
  • append ?token=... to the initial dashboard URL when [auth].api_key is configured
  • cover the launch URL builder with focused unit tests, including query encoding

This is the aw-tauri leg of the ActivityWatch API auth rollout.

Related:

Verification

  • cargo fmt --manifest-path src-tauri/Cargo.toml
  • prek run fmt --files src-tauri/src/lib.rs
  • prek run end-of-file-fixer --files src-tauri/Cargo.lock src-tauri/src/lib.rs
  • prek run check-added-large-files --files src-tauri/Cargo.lock src-tauri/src/lib.rs
  • cargo test --manifest-path src-tauri/Cargo.toml build_dashboard_url --lib (blocked locally: this machine is missing gdk-3.0 dev libraries, so Tauri/GTK deps fail before the crate compiles)

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 17, 2026

Greptile Summary

This PR bootstraps the aw-webui authentication credential into the Tauri dashboard URL on launch and bumps aw-server-rust to the auth-aware revision (which adds the subtle crate for constant-time comparisons).

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/5

Safe 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.

Security Review

  • Credential in HTTP access log (src-tauri/src/lib.rs, build_dashboard_url): The auth token is appended as a URL query parameter on the initial dashboard URL. Rocket will log the full request line on every app launch, writing the token value to the server's access log in plaintext. Risk is limited to local access log files, but log files on shared machines may have broader read permissions than the config file the token is sourced from.
  • No injection, secrets-in-source, or cross-origin issues identified. The addition of the subtle crate (constant-time comparisons) in the bumped aw-server-rust revision is a positive security signal for the auth implementation.

Important Files Changed

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
Loading

Reviews (1): Last reviewed commit: "feat(auth): bootstrap aw-webui token on ..." | Re-trigger Greptile

Comment thread src-tauri/src/lib.rs
Comment on lines +194 to +203
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
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security 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.

Comment thread src-tauri/src/lib.rs
Comment on lines +700 to +706
#[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"
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Space encoded as +, not %20

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.

@TimeToBuildBob
Copy link
Copy Markdown
Contributor Author

TimeToBuildBob commented Apr 20, 2026

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.

@ErikBjare ErikBjare merged commit 10322dc into ActivityWatch:master Apr 20, 2026
7 checks passed
@0xbrayo
Copy link
Copy Markdown
Member

0xbrayo commented Apr 20, 2026

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?

@0xbrayo
Copy link
Copy Markdown
Member

0xbrayo commented Apr 20, 2026

Screenshot 2026-04-20 at 22 00 23

@ErikBjare
Copy link
Copy Markdown
Member

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 --testing and apikey set in testing config to not mess with your prod instance).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants