Conversation
…es response formats
There was a problem hiding this comment.
This PR adds OAuth/PAT authentication, credential storage, URL-based board endpoint resolution, and Bearer propagation to board HTTP/WebSocket flows. The authentication behavior is largely isolated to the board-client path, but the endpoint migration changes the default contract used by every ostool board command.
Blocking issue:
- A newly created global config now resolves to
http://localhost/(HTTP port 80), whereas the existing client default and ostool-server default both use port 2999. Consequently a fresh install—or any board command before configuring a port—cannot reach the bundled/default server. Preserve:2999in the URL default or keepport = Some(2999)while retaining URL overrides, and add a resolution-level regression test.
Validation: helper self-tests passed and git diff --check passed. I could not run cargo fmt --check, clippy, or crate tests locally because this environment has no cargo binary. Both current GitHub Actions check (stable, x86_64-unknown-linux-gnu) runs succeeded; no CI failure is attributed to this PR.
Previous review comments and PR discussion: none were present. I found no materially overlapping authentication PR in the repository search. Remaining risk after the blocking fix is the unrun hardware/OAuth integration path; the current code changes real board, serial, and credential workflows.
Powered by gpt-5.6-terra
There was a problem hiding this comment.
This PR adds OAuth/PAT authentication and credential lifecycle handling, moves board endpoints to URL-based configuration, and propagates Bearer credentials through board HTTP and serial WebSocket requests. It addresses public authenticated board gateways, while retaining anonymous LAN mode; however, the global endpoint configuration is a shared contract for every existing ostool board command.
The current blocking issue is migration of existing global configuration, described inline. The base release writes [board] server_ip and port, but the new schema rejects that persisted format outright. This breaks upgrades before board commands—or the new login/status commands that load the same global config—can reach their endpoint.
Validation: both current GitHub Actions check (stable, x86_64-unknown-linux-gnu) runs succeeded, with no CI failure attributable to this PR. Locally, prepare-review, helper self-tests, and git diff --check origin/main...HEAD passed. The planned cargo fmt --check, package clippy with -D warnings, and package tests could not run because this environment has neither cargo nor rustc; no hardware/OAuth gateway integration was attempted.
Previous review feedback was considered: the earlier blocking default-port issue is resolved at this head (http://localhost:2999) and has a regression test. Its old inline comment is therefore resolved; no other actionable review or PR comments remain. A repository PR search found no overlapping authentication/client change (the other open PR is unrelated boot-readiness work).
Remaining risk after the requested migration is the unexercised real credential-store, OAuth, board, and serial-hardware paths. The configuration migration remains blocking.
Powered by gpt-5.6-terra
ostool登录与令牌管理变更说明变更内容与边界
本 PR 为
ostool增加登录、凭据保存、Token 刷新和注销能力,并将 board 服务地址统一为 URL 配置。ostool-server;现有匿名 board API 保持可用。配置与命令行
局域网仍使用匿名访问,但配置格式统一为 URL 型
server:公网认证网关使用完整 HTTPS 地址:
规则:
server必须为包含http://或https://的完整 URL;port为可选覆盖项;未填写时保留 URL 的显式端口或使用协议默认端口;auth_mode = "required"时必须使用 HTTPS;.board.toml可设置server、port、auth_mode,并由命令行参数覆盖。dev,原有的server_ip被替换为 URL 型server,原来必填的port变为可选覆盖项;命令行--server也必须使用完整 URL。新增命令:
客户端调用的认证网关接口
采用 OAuth 2.0 Device Authorization Grant,全部请求为
application/x-www-form-urlencoded。POST/oauth/device/codeclient_id=ostool-cli、scope=board:operate offline_accessPOST/oauth/tokengrant_type=urn:ietf:params:oauth:grant-type:device_code、device_code、client_idPOST/oauth/tokengrant_type=refresh_token、refresh_token、client_idPOST/oauth/revoketoken、token_type_hint=refresh_token、client_idDevice Code 响应至少应包含:
{ "device_code": "...", "user_code": "ABCD-EFGH", "verification_uri": "https://board.example.com/activate", "expires_in": 600, "interval": 5 }Token 响应应包含:
{ "access_token": "...", "refresh_token": "...", "token_type": "Bearer", "expires_in": 900 }scope为可选字段。服务端应在刷新时返回新的 Refresh Token,以支持 Token rotation。token_type必须为Bearer,expires_in必须为正数。轮询期间,认证网关应按 OAuth 约定以非 2xx 响应返回
authorization_pending或slow_down。客户端分别继续等待或将轮询间隔增加 5 秒;成功的 2xx 响应必须包含完整的 Token 字段。凭据与生命周期
凭据按认证网关 URL 隔离保存,优先使用系统 credential store:
系统凭据库不可用时,回退到
$XDG_CONFIG_HOME/ostool/hosts.json(或~/.config/ostool/hosts.json),并限制文件权限为0600。保存的敏感数据仅包括 OAuth Refresh Token、缓存的 Access Token 或 PAT。用户密码不落盘。
Token 使用策略:
auth_mode = "disabled":不读取、不发送 Token;OSTOOL_BOARD_ACCESS_TOKEN:只用于当前进程,不保存、不刷新;多个
ostool进程共用 Refresh Token 时,使用$XDG_CACHE_HOME/ostool/auth-locks/下的 URL 哈希锁文件避免并发刷新。收到invalid_grant、invalid_token或 board API 的401时,删除本地凭据并提示重新登录;临时网络错误保留凭据供后续重试。Board 请求认证
在
auth_mode = "required"时,所有现有 board REST 请求、文件上传和串口 WebSocket 握手均附加:Authorization: Bearer <access-token>认证模式下禁用 HTTP 重定向,并拒绝向不同 scheme、host 或 port 的绝对 WebSocket URL 发送 Token。匿名局域网模式不携带 Authorization Header。
修改范围
ostool/src/auth/:OAuth 客户端、凭据存储、Token 生命周期管理;server、可选port与auth_mode;login、logout、auth statusCLI;尚未提供 OAuth 生命周期、REST Bearer Header、凭据文件回退和
401凭据失效的 mock 网关自动化测试;这些场景列在下方作为手工验收项。验收
本地编译与自动化测试
cargo fmt --check cargo build -p ostool cargo test -p ostool --quiet cargo clippy -p ostool --all-targets -- -D warnings编译后的 CLI 位于
target/debug/ostool:本地匿名 board 服务
启动本地
ostool-server后,使用以下匿名配置验证局域网访问:本地认证网关
登录鉴权测试需要一个本地 HTTPS 认证网关;它应在同一 Base URL 下提供
/oauth/device/code、/oauth/token、/oauth/revoke,并代理或实现/api/v1/...board API。开发证书必须被操作系统信任,客户端不提供跳过 TLS 校验的选项。可先用 PAT 验证 Bearer Header 是否被携带:
可再用 mock 网关手工验证 Device Code 轮询、刷新、撤销、Refresh Token rotation、凭据文件回退和
401失效处理。可将 OAuth Token 响应的expires_in设为很短的值,再执行board ls确认刷新请求;不依赖真实开发板或真实公网服务。