短期 Web Login Ticket
短期 Web Login Ticket 用于把桌面端或移动端已有的 OAuth 登录状态一次性传给浏览器,并兑换成网站现有 User Session。它不新增 OAuth grant,也不建立另一套 Session。
OAuth access token -> 60 秒 ticket -> 浏览器一次性消费 -> 网站 User Session签发
POST /auth/web-login/tickets
Authorization: Bearer <wno-access-token>
Content-Type: application/json
{ "target": "personal-security" }{
"loginUrl": "https://frontend.example/auth/web-login#ticket=wn-web-...",
"expiresIn": 60
}OAuth token 必须包含 auth:web-login scope。这个能力由 OAuth App 管理面独立授权,后端不登记 client ID。target 只能从固定枚举中选择,不接受任意 URL;调用方不需要也不应该传 teamSlug。
target 枚举与落点
| target | 用途 | 网站落点 |
|---|---|---|
personal-security | 修改密码 / 账号安全 | /settings/personal/security |
billing-topup | 充值 | 账单页并自动打开充值弹窗 |
billing-transactions | 积分明细 | 积分明细页 |
billing-subscription | 订阅账单 / 管理 | 账单(订阅)页 |
消费响应会把签发时写入的 target 原样带回,前端据此映射到站内命名路由;缺失或未知时按 personal-security 兜底。
消费
POST /auth/web-login/consume
Content-Type: application/json
{ "ticket": "wn-web-..." }成功响应中的 user、session、created 与网站现有手机号/微信登录返回结构一致,另含本次票据绑定的 target。ticket 默认 60 秒有效,只能消费一次。
签发端缺少 scope 返回 insufficient_scope;账号未激活返回 invite_activation_required。消费端常见错误:ticket_invalid、ticket_expired、ticket_consumed、ticket_node_mismatch、oauth_authorization_revoked、service_unavailable。
复用规则
- ticket 原文只返回一次,数据库只保存 SHA-256 hash。
- ticket 绑定用户、OAuth token、client、固定 target 枚举、节点模式和前端 origin。
- 浏览器 URL 使用 fragment;网站在 router 启动前捕获并立即清除 fragment。
- 消费时原子标记已使用,并再次确认原 OAuth 授权和
auth:web-loginscope 仍有效。 - 新增目标时扩展固定 target 枚举(数据库 CHECK、后端校验、前端落点映射三处同步),不接受任意跳转 URL,不复制新的 Session 实现。
完整实现说明与复用检查项见仓库开发文档 docs/features/auth/web-login-ticket.md。
修改密码
网页登录完成后使用网站 User Session 调用:
POST /my/password/change
Authorization: Bearer <user-session>
Content-Type: application/json
{ "currentPassword": "...", "newPassword": "..." }稳定错误码包括 current_password_invalid、password_not_configured、password_unchanged、invalid_request 和 service_unavailable。
财务目标的团队归属与重试
billing-topup、billing-transactions、billing-subscription 进入网页后,统一经 /settings/billing/entry 使用当前登录用户的 GET /billing/summary 返回的 teamId 解析默认个人团队,并同步网站团队状态,再进入充值/明细/订阅页。网站此前选中的其他团队不作为财务票据的落点。
摘要或团队加载失败保留入口及原 target,显示重试;重试刷新团队信息。无个人团队显示明确提示,可在新标签中管理/创建团队,再回原入口重试。入口需要网页登录态;这不改变 Driver 签发票据所需的 auth:web-login 和摘要所需的 billing:read。成功后清除 target,充值动作仍由一次性 topup=1 触发。Driver 订阅卡片的“前往默认个人团队”也通过该入口同步状态。