Skip to content

fix: harden dashboard auth across SDK servers#408

Merged
pratyush618 merged 12 commits into
masterfrom
fix/dashboard-auth-hardening
Jul 11, 2026
Merged

fix: harden dashboard auth across SDK servers#408
pratyush618 merged 12 commits into
masterfrom
fix/dashboard-auth-hardening

Conversation

@pratyush618

@pratyush618 pratyush618 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Audit of the dashboard servers confirmed every /api/* route is already enforced server-side by a single pre-routing gate in each SDK (401 → session-bound CSRF → admin RBAC). This PR closes the gaps that sat outside that gate, keeping behaviour identical across all three servers.

Probe endpoints no longer bypass auth

/metrics and /readiness were reachable without credentials in every mode unless TASKITO_DASHBOARD_METRICS_TOKEN happened to be set — exposing the Prometheus registry and worker/storage health on auth-enabled deployments. With auth enabled they now require either the metrics bearer token (scraper-friendly) or the mode's own credential (valid session, or shared token in legacy mode). Open mode is unchanged, and /health stays public for liveness probes.

Query-string token restricted to page-load bootstrap

Legacy token mode accepted ?token= on API calls, leaking the secret into access logs, browser history, and Referer headers. API requests now accept the token only via header or cookie; a valid ?token= on a page load sets the httpOnly cookie once and 302-redirects with the token stripped from the URL.

OAuth first-user-admin fallback removed

With no admin allowlist configured, the first verified-email OAuth login became admin — a first-login-wins race on misconfigured deployments. OAuth users now always get the viewer role unless listed in TASKITO_DASHBOARD_OAUTH_ADMIN_EMAILS; admin access otherwise comes from the setup flow or env bootstrap. A startup warning fires when providers are configured without an allowlist.

Tests

  • Viewer-403-on-mutation and probe-gating matrices per auth mode, plus query-token bootstrap coverage.
  • Python: 284 dashboard tests, ruff, mypy green. Node: 96 dashboard tests, tsc green. Java: Dashboard/AuthStore/OAuth suites green.

Docs

7 pages updated: probe gating semantics, scraper token guidance, OAuth role rules, token-mode auth sources.

Summary by CodeRabbit

  • Security
    • Improved dashboard token handling: query tokens are accepted only for one-time page-load authentication, while API requests require headers or cookies.
    • Added consistent authentication controls for readiness and metrics endpoints, with optional bearer-token access.
  • Bug Fixes
    • OAuth users now receive admin access only when their verified email is explicitly allowlisted; others receive viewer access.
  • Documentation
    • Updated Java, Node.js, and Python guides to reflect authentication, probe access, and OAuth role behavior.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6a2ef710-03e3-48d4-9203-eaa48ab8881d

📥 Commits

Reviewing files that changed from the base of the PR and between 068b4f0 and f8ca670.

📒 Files selected for processing (7)
  • docs/content/docs/java/guides/operations/dashboard.mdx
  • docs/content/docs/node/guides/operations/dashboard.mdx
  • sdks/java/src/main/java/org/byteveda/taskito/dashboard/auth/oauth/OAuthFlow.java
  • sdks/java/src/test/java/org/byteveda/taskito/dashboard/DashboardAuthTest.java
  • sdks/node/src/dashboard/auth/tokenAuth.ts
  • sdks/node/src/dashboard/server.ts
  • sdks/node/test/dashboard/sessionAuth.test.ts
📝 Walkthrough

Walkthrough

Dashboard authentication now separates page-load token bootstrapping from API credentials, protects readiness and metrics according to auth mode, and removes first-user OAuth admin assignment across SDKs. Documentation and tests reflect the updated behavior.

Changes

Dashboard authentication and authorization

Layer / File(s) Summary
Token bootstrap and credential sources
sdks/java/.../dashboard/*, sdks/node/src/dashboard/*, sdks/java/src/test/..., sdks/node/test/dashboard/*, docs/content/docs/{java,node}/...
Query tokens only bootstrap page-load cookies and redirect; API requests use bearer headers, X-Taskito-Token, or cookies.
Unified probe authorization
sdks/java/src/main/.../DashboardServer.java, sdks/node/src/dashboard/server.ts, sdks/python/taskito/dashboard/server.py, sdks/*/test/*, docs/content/docs/{java,node,python}/...
/health remains public, while /readiness and /metrics require the configured auth-mode credential or metrics bearer token when applicable.
OAuth role assignment and diagnostics
sdks/{java,node,python}/.../auth*, sdks/{java,node,python}/.../oauth*, docs/content/docs/{java,python}/.../sso.mdx
OAuth admin assignment now requires a verified email in the admin allowlist; unallowlisted users receive viewer, and missing allowlists produce warnings.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant DashboardServer
  participant AuthStore
  Client->>DashboardServer: Request dashboard probe
  DashboardServer->>AuthStore: Check session when required
  DashboardServer-->>Client: Return probe data or 401
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: dashboard auth hardening across SDK servers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dashboard-auth-hardening

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
sdks/java/src/test/java/org/byteveda/taskito/dashboard/DashboardAuthTest.java (1)

187-207: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Exercise the bootstrapped cookie as an authenticated credential.

Assert the cookie is HttpOnly, then replay its name=value on /api/stats and expect 200. The current assertion only verifies a cookie prefix, so a non-HttpOnly or unusable bootstrap cookie would pass.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@sdks/java/src/test/java/org/byteveda/taskito/dashboard/DashboardAuthTest.java`
around lines 187 - 207, Update queryTokenOnlyBootstrapsPageLoads to capture the
bootstrapped taskito_token cookie, assert its Set-Cookie value includes the
HttpOnly attribute, then replay its name=value as the request Cookie on
/api/stats and assert a 200 response. Preserve the existing redirect, token
stripping, and wrong-token assertions.
sdks/node/test/dashboard/auth.test.ts (1)

63-74: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Verify the bootstrap cookie’s security and usability.

Also require HttpOnly and send the returned cookie on an API request that succeeds. Checking only for taskito_token= would miss a client-readable or malformed credential.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/node/test/dashboard/auth.test.ts` around lines 63 - 74, The page-load
token bootstrap test should verify the returned taskito_token cookie includes
the HttpOnly attribute, then reuse that cookie in a subsequent authenticated API
request and assert the request succeeds. Update the test covering the valid
?token= flow while preserving the existing redirect and query-stripping
assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/content/docs/java/guides/operations/dashboard.mdx`:
- Around line 189-193: Update the first-run public-route list in the dashboard
operations guide to remove `/readiness` and `/metrics`, leaving only routes that
remain public during session-auth setup; preserve the later authorization
behavior description and the `/health` entry.
- Around line 171-174: Update the dashboard authentication documentation near
the token redirect description to remove the claim that the redirect prevents
access-log exposure. State that it strips the token from subsequent browser
history/navigation and Referer propagation, and explicitly instruct operators to
redact query strings in server and proxy access logs.

In `@docs/content/docs/node/guides/operations/dashboard.mdx`:
- Around line 64-66: Update the dashboard authentication documentation around
the httpOnly-cookie redirect description to remove the claim that it prevents
access-log exposure. Limit the stated protection to browser history and later
Referer propagation, and advise redacting the token from query strings in access
logs.

In `@sdks/node/src/dashboard/server.ts`:
- Around line 117-121: Update the bootstrapped token-cookie flow in the GET
authentication branch to pass options.secureCookies !== false to setTokenCookie,
and extend the helper’s cookie attributes to append Secure unless that value is
explicitly disabled. Preserve plain-HTTP development through the explicit false
opt-out.

In `@sdks/node/test/dashboard/sessionAuth.test.ts`:
- Around line 240-251: Update the test around the metrics-token setup to capture
the existing TASKITO_DASHBOARD_METRICS_TOKEN value before overwriting it, then
restore that value in finally; only delete the environment variable when it was
originally unset.

---

Nitpick comments:
In
`@sdks/java/src/test/java/org/byteveda/taskito/dashboard/DashboardAuthTest.java`:
- Around line 187-207: Update queryTokenOnlyBootstrapsPageLoads to capture the
bootstrapped taskito_token cookie, assert its Set-Cookie value includes the
HttpOnly attribute, then replay its name=value as the request Cookie on
/api/stats and assert a 200 response. Preserve the existing redirect, token
stripping, and wrong-token assertions.

In `@sdks/node/test/dashboard/auth.test.ts`:
- Around line 63-74: The page-load token bootstrap test should verify the
returned taskito_token cookie includes the HttpOnly attribute, then reuse that
cookie in a subsequent authenticated API request and assert the request
succeeds. Update the test covering the valid ?token= flow while preserving the
existing redirect and query-stripping assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9aff26b7-429e-4155-86d0-28df152c1337

📥 Commits

Reviewing files that changed from the base of the PR and between 33c829c and 068b4f0.

📒 Files selected for processing (27)
  • docs/content/docs/java/guides/operations/dashboard.mdx
  • docs/content/docs/java/guides/operations/sso.mdx
  • docs/content/docs/node/guides/operations/dashboard-api.mdx
  • docs/content/docs/node/guides/operations/dashboard.mdx
  • docs/content/docs/python/guides/dashboard/authentication.mdx
  • docs/content/docs/python/guides/dashboard/sso.mdx
  • docs/content/docs/python/guides/operations/security.mdx
  • sdks/java/src/main/java/org/byteveda/taskito/dashboard/DashboardServer.java
  • sdks/java/src/main/java/org/byteveda/taskito/dashboard/auth/AuthStore.java
  • sdks/java/src/main/java/org/byteveda/taskito/dashboard/auth/TokenAuth.java
  • sdks/java/src/main/java/org/byteveda/taskito/dashboard/auth/oauth/OAuthFlow.java
  • sdks/java/src/test/java/org/byteveda/taskito/dashboard/DashboardAuthTest.java
  • sdks/java/src/test/java/org/byteveda/taskito/dashboard/DashboardTest.java
  • sdks/java/src/test/java/org/byteveda/taskito/dashboard/auth/AuthStoreTest.java
  • sdks/java/src/test/java/org/byteveda/taskito/dashboard/oauth/OAuthFlowTest.java
  • sdks/node/src/dashboard/auth/oauth/flow.ts
  • sdks/node/src/dashboard/auth/store.ts
  • sdks/node/src/dashboard/auth/tokenAuth.ts
  • sdks/node/src/dashboard/server.ts
  • sdks/node/test/dashboard/auth.test.ts
  • sdks/node/test/dashboard/oauth.test.ts
  • sdks/node/test/dashboard/oauthEndpoints.test.ts
  • sdks/node/test/dashboard/sessionAuth.test.ts
  • sdks/python/taskito/dashboard/auth.py
  • sdks/python/taskito/dashboard/oauth/flow.py
  • sdks/python/taskito/dashboard/server.py
  • sdks/python/tests/dashboard/test_auth.py

Comment thread docs/content/docs/java/guides/operations/dashboard.mdx Outdated
Comment thread docs/content/docs/java/guides/operations/dashboard.mdx
Comment thread docs/content/docs/node/guides/operations/dashboard.mdx Outdated
Comment thread sdks/node/src/dashboard/server.ts
Comment thread sdks/node/test/dashboard/sessionAuth.test.ts Outdated
@pratyush618 pratyush618 merged commit 835b2f8 into master Jul 11, 2026
34 checks passed
@pratyush618 pratyush618 deleted the fix/dashboard-auth-hardening branch July 11, 2026 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant