可用于实现 AtomGit 平台的扫码登录功能,支持终端显示二维码、轮询授权状态及 token 安全存储,提供 OAuth 客户端 API,包含自动刷新过期 token 等安全特性。【此简介由AI生成】
AtomGit 扫码登录 - Go 实现
基于 AtomGit OAuth Broker 的扫码登录 Go 语言实现。参考 Rust 实现 atomcode-core/auth/oauth.rs 完整移植。
架构概述
三方模型:终端设备 ↔ Broker (acs.atomgit.com) ↔ atomgit.com
- Broker 持有与 atomgit.com 的 OAuth 握手(含 client secret)
- 设备端零密钥,只拿一个不透明的
state串联整条流 - 二维码本质是把 broker 返回的
login_url编码成 QR
安装
# 克隆项目
git clone <repository-url>
cd Gitcode-login
# 安装依赖并编译
go mod tidy
go build -o atomcode-login server.go
快速开始
方式一:HTTP 服务模式(适合 Agent 调用)
# 编译
go build -o atomcode-login-server server.go
# 启动服务(监听 :8080)
./atomcode-login-server
服务启动后,Agent 可以通过 REST API 分步调用登录流程(参见下方 HTTP 服务 API 章节)。
环境变量
| 变量 | 说明 | 默认值 |
|---|---|---|
ATOMCODE_PLATFORM_SERVER |
Broker URL | https://acs.atomgit.com |
ATOMCODE_HOME |
配置目录 | ~/.atomcode |
API 文档
OAuth 客户端
import "github.com/atomgit/atomcode-oauth/auth"
// 创建 OAuth 客户端
o := auth.NewOAuth("yourapp/1.0.0", "/path/to/auth.toml")
// 发起登录
loginResp, err := o.StartLogin()
// 返回: { login_url, state }
// 轮询检查
checkResp, err := o.Poll(state)
// 返回: { valid: true|false }
// 获取 token
token, err := o.Finish(state)
// 返回: { access_token, refresh_token, user, ... }
// 刷新 token
newToken, err := o.RefreshAccessToken(refreshToken)
// 获取有效 token(自动刷新过期 token)
token, err := o.GetValidToken()
Token 存储
// 安全写入 auth.toml
auth.WriteAuthFileSecure(path, &auth.AuthFile{
AccessToken: "...",
RefreshToken: "...",
TokenType: "Bearer",
ExpiresIn: 3600,
CreatedAt: time.Now().Unix(),
User: &auth.User{...},
})
// 读取 auth.toml
authFile, err := auth.ReadAuthFile(path)
二维码渲染
// ASCII 二维码(适合终端)
qrASCII, err := auth.RenderQRCodeASCII(url)
// 终端彩色二维码
qrTerminal, err := auth.RenderQRCodeTerminal(url)
// PNG Base64(适合 GUI)
qrPNG, err := auth.RenderQRCodeWithSize(url, 256)
Broker API 契约
Base URL: https://acs.atomgit.com
| 步骤 | 请求 | 响应 |
|---|---|---|
| 发起 | GET /auth/login?provider=atomgit |
{ login_url, state } |
| 轮询 | GET /auth/check?state=<state> |
`{ valid: true |
| 换 token | GET /auth/token?state=<state> |
{ access_token, refresh_token?, user? } |
| 刷新 | POST /oauth/refresh body { refresh_token } |
{ access_token, ... } |
auth.toml 格式
access_token = "..."
refresh_token = "..." # 可选
token_type = "Bearer"
expires_in = 3600 # 可选,秒
created_at = 1719500000 # 收到 token 时的 unix 秒
[user]
id = "..."
username = "..."
name = "..." # 可选
email = "..." # 可选
avatar_url = "..." # 可选
安全特性
- 目录权限
chmod 700 - 文件权限
chmod 600 - 原子写入:临时文件 → fsync → rename
- 提前 5 分钟刷新过期 token
- 系统时间容错:获取失败时强制刷新
HTTP 服务 API(Agent 调用)
适合在 Agent 中调用,每个接口都是立即返回,非阻塞。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /login/start |
发起登录,返回 session_id、URL、二维码 |
| GET | /login/poll?session_id=xxx |
查询登录状态(立即返回) |
| GET | /login/finish?session_id=xxx |
获取最终 token |
Agent 调用流程
1. Agent 调用 POST /login/start
→ 立即返回 { session_id, login_url, qr_code, qr_code_png }
2. Agent 展示二维码和 URL 给用户
→ 用户扫码授权
3. Agent 循环调用 GET /login/poll?session_id=xxx
→ 每次调用立即返回状态: "waiting" 或 "authorized"
4. 当状态变为 "authorized",调用 GET /login/finish?session_id=xxx
→ 返回 { access_token, refresh_token, user }
API 调用示例
# 1. 发起登录
curl -X POST http://localhost:8080/login/start
# 返回:
# {
# "session_id": "session_1",
# "login_url": "https://acs.atomgit.com/s/xxx",
# "qr_code": "████████████████...",
# "qr_code_png": "data:image/png;base64,..."
# }
# 2. 轮询状态
curl "http://localhost:8080/login/poll?session_id=session_1"
# 返回: { "session_id": "session_1", "status": "waiting" }
# 3. 用户授权后状态变为 authorized
curl "http://localhost:8080/login/poll?session_id=session_1"
# 返回: { "session_id": "session_1", "status": "authorized" }
# 4. 获取 token
curl "http://localhost:8080/login/finish?session_id=session_1"
# 返回: { "access_token": "...", "user": { "username": "..." } }
登录流程
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1. 发起 │ → │ 2. 轮询 │ → │ 3. 完成 │
│ StartLogin │ │ Poll 每2s │ │ Finish │
│ │ │ ↻ valid? │ │ │
│ login_url │ │ false→等 │ │ token+user │
│ state │ │ true→跳 │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
依赖
- github.com/BurntSushi/toml - TOML 解析
- github.com/skip2/go-qrcode - 二维码生成
参考
License
MIT