Skip to content

feat(auth): bootstrap API token from URL/session#806

Merged
ErikBjare merged 2 commits intoActivityWatch:masterfrom
TimeToBuildBob:feat/api-key-bootstrap
Apr 20, 2026
Merged

feat(auth): bootstrap API token from URL/session#806
ErikBjare merged 2 commits intoActivityWatch:masterfrom
TimeToBuildBob:feat/api-key-bootstrap

Conversation

@TimeToBuildBob
Copy link
Copy Markdown
Contributor

Summary

  • load ?token=... from the browser URL into tab-scoped sessionStorage
  • strip the token from the address bar after bootstrap while preserving other query params and hash
  • apply Authorization: Bearer ... to the shared aw-webui client defaults
  • add regression tests for URL parsing, persistence, cleanup, and header injection

Context

This is the remaining aw-webui piece of the ActivityWatch API auth rollout discussed in ActivityWatch/activitywatch#1199. It makes browser access work when a launcher/WebView opens aw-webui with a tokenized URL.

Testing

  • npx eslint --ext=js,ts src/util/awclient.ts test/unit/awclient.test.js
  • npx jest --runInBand --runTestsByPath test/unit/awclient.test.js test/unit/NewReleaseNotification.test.js test/unit/store/activity.test.node.ts
  • npx tsc --noEmit --pretty false

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 17, 2026

Codecov Report

❌ Patch coverage is 91.66667% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 31.53%. Comparing base (5529031) to head (c00a46f).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/util/awclient.ts 91.66% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #806      +/-   ##
==========================================
+ Coverage   29.96%   31.53%   +1.57%     
==========================================
  Files          32       32              
  Lines        1829     1877      +48     
  Branches      317      331      +14     
==========================================
+ Hits          548      592      +44     
- Misses       1260     1264       +4     
  Partials       21       21              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 17, 2026

Greptile Summary

This PR implements API auth bootstrapping in aw-webui: a credential read from a URL query parameter is persisted to tab-scoped sessionStorage, stripped from the address bar via history.replaceState, and applied to the shared AWClient Axios request defaults. Prior review concerns around loose typing, stale module singleton in tests, and URL-exposure documentation are all resolved in the head commit.

Confidence Score: 5/5

Safe to merge — implementation is correct, prior P0/P1 concerns are resolved, and tests cover all key paths.

All three previously raised issues (loose any typing, stale singleton in tests, URL-exposure documentation) are addressed in the head commit. No new P0 or P1 issues were found during this review. The remaining code patterns (defensive SSR guards, normalizeToken fallback, replaceState URL cleanup) are correct and well-tested.

No files require special attention.

Important Files Changed

Filename Overview
src/util/awclient.ts Adds token bootstrap logic (URL → sessionStorage → Axios header), with SSR guards, URL cleanup, and proper AxiosInstance typing; no issues found.
test/unit/awclient.test.js New jsdom test suite with jest.resetModules() per-test isolation, covering URL parse, persist, strip, and header injection; coverage looks complete.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant awclient.ts
    participant sessionStorage
    participant history
    participant AxiosDefaults

    Browser->>awclient.ts: createClient()
    awclient.ts->>awclient.ts: loadApiTokenFromBrowser()
    awclient.ts->>Browser: getApiTokenFromLocation(window.location)
    alt token in URL
        awclient.ts->>sessionStorage: setItem('aw-api-token', token)
        awclient.ts->>history: replaceState() — strip ?token= from URL
        awclient.ts-->>awclient.ts: return urlToken
    else no URL token
        awclient.ts->>sessionStorage: getItem('aw-api-token')
        awclient.ts-->>awclient.ts: return storedToken (or null)
    end
    awclient.ts->>AxiosDefaults: applyApiToken — set headers.common.Authorization
Loading

Reviews (2): Last reviewed commit: "fix(auth): address review feedback — typ..." | Re-trigger Greptile

Comment thread src/util/awclient.ts
Comment thread src/util/awclient.ts Outdated
Comment thread test/unit/awclient.test.js
…isolation

- Replace `defaults: any` with `{ req: AxiosInstance }` for proper type checking
- Document token URL exposure window with mitigation guidance
- Use jest.resetModules() to reset module-level _client between tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@TimeToBuildBob
Copy link
Copy Markdown
Contributor Author

Addressed the Greptile findings in c00a46f:

  1. Token URL exposure — added a doc comment on loadApiTokenFromBrowser noting the exposure window and fragment-based mitigation for general browser use.
  2. Loose any type — replaced defaults: any with { req: AxiosInstance } so TypeScript catches header typos.
  3. Test isolation — switched to jest.resetModules() + dynamic re-import in beforeEach so the module-level _client singleton resets between tests.

@ErikBjare
Copy link
Copy Markdown
Member

@greptileai review

@ErikBjare ErikBjare merged commit dd7ae07 into ActivityWatch:master Apr 20, 2026
8 checks passed
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.

2 participants