Skip to content

feat(web): protect launcher dashboard with token and SPA login#1953

Open
zeed-w-beez wants to merge 8 commits intosipeed:mainfrom
zeed-w-beez:feature/dashboard-launcher-token
Open

feat(web): protect launcher dashboard with token and SPA login#1953
zeed-w-beez wants to merge 8 commits intosipeed:mainfrom
zeed-w-beez:feature/dashboard-launcher-token

Conversation

@zeed-w-beez
Copy link

📝 Description

背景与目标

Launcher 内嵌的 Web Dashboard 与 /api/* 需要访问控制,避免在暴露端口(含 LAN)时被未授权访问。本 PR 为 Dashboard 增加基于 launcher-config.jsondashboard_token(或环境变量 PICOCLAW_LAUNCHER_TOKEN 的认证:浏览器侧通过登录页提交令牌后写入 HttpOnly Cookie,或使用 Authorization: Bearer <token>

改动摘要

  • 后端
    • 新增 launcherconfigdashboard_tokenauth_signing_key 的生成/持久化及 PICOCLAW_LAUNCHER_TOKEN 覆盖;单元测试。
    • POST/GET /api/auth/login|logout|status:校验令牌、设置/清除会话 Cookie(SameSite=Lax,HTTPS 下 Secure)。
    • 中间件 LauncherDashboardAuth:除公开路径外要求有效 Cookie 或 Bearer;对路径做 path.Clean 规范化,避免 /assets/../api/... 类绕过;公开 /launcher-login/assets/* 及 favicon/manifest 等静态资源以便 SPA 登录页加载。
    • main.go:注册上述路由与中间件栈。
    • gateway_host:补充 buildPicoEventsURL / buildPicoSendURL(及 requestHTTPScheme),/api/pico/token 等响应携带 events_url / send_url,与现有 buildWsURL 一致走 Web 端口。
  • 前端
    • 新增路由 /launcher-login:React 登录表单、i18n、主题/语言切换;launcher-auth 使用普通 fetch 登录,避免与 401 跳转逻辑冲突。
    • launcherFetch:带 Cookie 的请求;401 + JSON 时跳转登录页;已在登录页时不再跳转以防循环;各 API 模块统一改用 launcherFetch
    • __root:在登录路由下不挂载 AppLayout、不初始化 chat store;用 地址栏 pathname ∪ 路由 判断登录页,避免网关轮询 401 导致重载循环。
    • lib/launcher-login-path:路径规范化复用。
    • routeTree.gen.ts:注册 /launcher-login
  • 构建与文档
    • Makefilebuild-launcher 始终执行 pnpm build:backend,避免陈旧 dist 嵌入导致路由缺失。
    • documents/web_launcher_dashboard_auth.md:行为简述。
  • 其他
    • security_integration_test:去掉未导出字段上的 json 标签以通过 vet(语义不变:encoding/json 仍不写入未导出字段)。

影响

  • Core Feature(安全相关:默认启用 Dashboard 访问控制)
  • 首次保存 launcher-config.json 可能写入随机 dashboard_token / auth_signing_key;若设置 PICOCLAW_LAUNCHER_TOKEN,以环境变量为准。

🗣️ Type of Change

  • 🐞 Bug fix
  • ✨ New feature
  • 📖 Documentation update(documents/ 短文)
  • ⚡ Code refactoring(仅部分可读性/一致性调整)

🤖 AI Code Generation

  • 🤖 Fully AI-generated
  • 🛠️ Mostly AI-generated
  • 👨‍💻 Mostly Human-written

🔗 Related Issue

📚 Technical Context

  • Reference: 设计说明见仓库内 documents/web_launcher_dashboard_auth.md
  • Reasoning: Cookie + Bearer 双路径兼顾浏览器与脚本;会话 Cookie 值为 HMAC(签名密钥, token),不落库明文会话表;静态资源白名单与规范化路径降低误拦与绕过风险。

🧪 Test Environment

  • Hardware/OS:
  • 验证建议:
    • make check / go test ./web/backend/... 通过
    • make build-launcher 后:无 Cookie 访问 / → 重定向或 API 401 → 登录页;登录后正常访问 Dashboard 与聊天相关 API
    • 登录页:语言/主题、提交错误令牌、网络错误提示

☑️ Checklist

  • 本地 make check(或等价检查)通过
  • 已自审 diff
  • 已更新 documents/(或确认无需更长文档)

@sipeed-bot sipeed-bot bot added type: enhancement New feature or request domain: config labels Mar 24, 2026
@yinwm yinwm mentioned this pull request Mar 24, 2026
10 tasks
@yinwm
Copy link
Collaborator

yinwm commented Mar 24, 2026

Hi @zeed-w-beez, great work on this PR! 🎯

However, CI is failing and needs to be fixed before merging:

❌ Failed Checks

Check Status Log
Linter FAIL Details
Tests FAIL Details

🐛 Root Cause

File: web/backend/api/config_test.go:173:13

Error:

cannot use config.ChannelsSecurity{…} (value of struct type config.ChannelsSecurity) 
as *config.ChannelsSecurity value in struct literal

This is related to the change in pkg/config/security_integration_test.go where json tags were removed from unexported fields.

🔧 Suggested Fix

The test is trying to use a struct value where a pointer is expected. Either:

  1. Change the test to use &config.ChannelsSecurity{...} (take address)
  2. Or change the field type to value instead of pointer

Please fix and push a new commit! Looking forward to seeing this merged. 👍

@zeed-w-beez zeed-w-beez force-pushed the feature/dashboard-launcher-token branch from efbeab9 to c3598f5 Compare March 25, 2026 00:22
@zeed-w-beez
Copy link
Author

CI is fixed and green. Ready to merge. @yinwm

@zeed-w-beez zeed-w-beez force-pushed the feature/dashboard-launcher-token branch 3 times, most recently from 7e0b5d7 to ac6a016 Compare March 26, 2026 01:15
@zeed-w-beez
Copy link
Author

rebase main.

…dling

- Added dashboard token and signing key management in launcher configuration.
- Integrated dashboard authentication into the API routes.
- Updated frontend API calls to use `launcherFetch` for consistent request handling.
- Introduced new routes for launcher login and improved URL generation for Pico events and WebSocket connections.
- Enhanced tests for dashboard secrets and URL building logic.
- Updated the login process to allow automatic token submission via URL, improving user experience.
- Refactored login handling to utilize a dedicated function for better code organization and error management.
- Added validation for search parameters to ensure proper token handling in the login route.
…onfiguration

- Reformatted function signatures and variable assignments for better clarity.
- Enhanced the EnsureDashboardSecrets function with multi-line parameters for improved readability.
- Adjusted variable unpacking in tests to align with updated function signatures.
- Adjusted the test for JSON unmarshalling to clarify that unexported fields are not populated, regardless of the presence of JSON tags.
- Removed the JSON tag from the private field in the test struct to reflect this behavior accurately.
- Implemented token-based login via URL query parameters for the launcher dashboard.
- Updated session cookie management to improve security and streamline login flow.
- Refactored related functions for better readability and maintainability.
- Added tests to validate the new token handling behavior in various scenarios.
… unnecessary config parameter

- Updated the `buildWsURL`, `buildPicoEventsURL`, and `buildPicoSendURL` functions to eliminate the unused `cfg` parameter.
- Adjusted related tests to reflect the changes in function signatures.
- Enhanced the `picoWebUIAddr` function to ensure it uses the request's host directly, improving URL accuracy for browser clients.
@zeed-w-beez zeed-w-beez force-pushed the feature/dashboard-launcher-token branch from ac6a016 to 9c53b71 Compare March 26, 2026 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants