自动授权(免确认发码)
用户点了站点的「登录」按钮之后,如果此前已经同意过这个应用,CaelLabID 不会再弹一遍授权页 —— 直接发授权码把用户送回站点。虚舟实验室第一方应用(developer_id = 1)在用户开着「快速登录」(默认开启)时更进一步:只显示一个自动走完的过渡页,用户不需要点任何东西。
这篇文章讲什么
它讲的是用户点了「登录」之后少要点几下。
站点的自动登录(页面加载时悄悄探测你在 CaelLabID 登没登、然后把你无感登进去)已于 2026-09-26 全部下线:CaelLabSearch、CodingCommunity 等接入站都不会再在你没点过任何东西的时候发起授权。想登录就点「登录」,一次点击的事。
什么情况下不用再确认
| 应用类型 | 前提 | 用户点「登录」之后 |
|---|---|---|
第一方应用(developer_id = 1) | 用户开着「快速登录」(默认开启) | 走一个自动完成的过渡页,直接发码;回调额外带 spicallogin |
| 第三方应用 | 用户此前同意过,且请求的 scope 没超出已同意的范围 | 直接发码,不弹授权页(用的就是当初同意的那些 scope) |
| 第三方应用 | 没同意过,或 scope 超出了已同意的范围 | 显示授权页,由用户自己勾选同意 |
| 任何应用 | 用户在 CaelLabID 未登录 | 跳登录页 —— 用户确实点过登录,这一跳是预期内的 |
- 第一方应用首次接入也是自动的:本次 scope 会隐式写进授权记录,用户在仪表盘的已授权列表里看得到、也能随时撤销(不是「不留痕迹」的静默授权)。
- 回调上的
spicallogin只在这条「没渲染过任何需要点的页面」的路上带(当前值是一个固定的 slug)。只判断有没有这个参数,不要比对它的值 —— CaelLabID 改过一次值、参数名没动。收到它建议给用户一句提示,否则用户会以为自己没登上。 - 第三方应用第一次接入必然要过一次授权页(用户主动点登录那一次),从那以后才免确认。
透明度:它做了什么、没做什么
- 站点不会在页面加载时查询你的登录状态 —— 「自动登录探测」那套机制已经全部下线,现在没有任何接入站在做这件事。
- 只有你点了「登录」,浏览器才会走一次
GET /oauth/authorize。 - 站点拿到的只是一次授权的结果(授权码,或一个错误码)。身份信息只能由站点后端拿授权码去换
/api/userinfo,而且每个应用拿到的sub都是独立的(同一个人在不同应用里是不同的标识)。
你能怎么关:
| 想要的效果 | 怎么做 |
|---|---|
| 第一方应用首次也别自动发码 | 在 CaelLabID 的账号设置里关掉「快速登录」 |
| 让某个应用下次重新征求同意 | 在 CaelLabID 仪表盘的已授权列表里撤销它 |
| 让某个站点忘掉你 | 点那个站点顶栏的「退出」(纯本地退出:只清那个站点的会话,你在 CaelLabID 的登录状态和 授权记录都还在,再点一次登录就回来了) |
接入方要注意的
- 回跳地址只从 session 取,并过一遍本地路径白名单(只接受站内路径)—— 这处放开就是开放重定向。
- scope 要在开放平台登记:登记值、服务端全局 scope、请求的 scope 三者取交集。只登记
openid的应用拿不到profile,就没有昵称和头像。 - 回调的查询串不止
code/state:第一方应用 + 快速登录时会多带spicallogin。别写「查询串里只准有这两个参数」那种校验。 - 授权码 10 分钟有效,从发放时开始算,与用户此前在 CaelLabID 停留多久无关。
验证
登录链路里夹着 CaelLabID 自己的两步验证,没法用脚本跑通完整登录(自动化过不了那一步),端到端只能让本人点一次。
能脚本验掉的是接口行为:
# 未登录时打授权端点 :应 302 到登录页,而不是直接发码
curl -si "https://id.caellab.com/oauth/authorize?response_type=code&client_id=<你的 client_id>\
&redirect_uri=<你的回调地址>&scope=openid%20profile&state=t1" | grep -i '^location'
# 期望:/login?redirect_to=%2Foauth%2Fauthorize…
接口另外按 OIDC 规范保留 prompt=none(带上它就绝不渲染页面:未登录回 error=login_required、需要交互回 error=interaction_required)。接入站现在不做自动登录,用不到它,参数说明见授权端点。