Go集成飞书登录需手写OAuth2授权码流程:1.构造含app_id、redirect_uri、state等参数的授权URL;2.回调校验state后,以x-www-form-urlencoded格式用code换token;3.用Bearer Token调用user_info接口获取data.user_id等非标字段,refresh_token须加密存库并每次刷新覆盖。

Go 语言集成飞书登录,本质是实现 OAuth2 授权码模式(Authorization Code Flow),不是调用某个现成的 feishu.Login() 函数——飞书官方没有提供 Go SDK 封装该流程,必须手写 HTTP 请求与状态管理。
为什么不能直接用第三方 OAuth 库自动完成?
飞书 OAuth2 接口行为和标准略有差异,容易踩坑:
- 飞书的
authorization_endpoint不返回state参数校验失败时的明确错误页,而是静默跳回 redirect_uri + 错误 query(如?error=invalid_scope),很多通用库会忽略或解析错 token_endpoint要求以application/x-www-form-urlencoded发送 POST,且必须带grant_type=authorization_code,部分库默认发 JSON 会 400- 飞书返回的 access_token 是短期(2 小时),但配套的
refresh_token有效期长达 30 天——必须自己持久化并主动刷新,通用库常只做单次换 token - 飞书用户信息接口
https://open.feishu.cn/open-apis/authen/v1/user_info需要 Bearer Token,且响应字段名是data.user_id、data.en_name等,不是标准的sub/name
关键三步:获取 code → 换 token → 拉用户信息
核心逻辑用 net/http + encoding/json 即可完成,无需额外框架:
1. 构造授权 URL(服务端生成,重定向用户):
authURL := "https://open.feishu.cn/open-apis/authen/v1/index?" + url.Values{
"app_id": {"your_app_id"},
"redirect_uri": {"https://yourdomain.com/callback"},
"response_type": {"code"},
"scope": {"user_info"},
"state": {uuid.New().String()}, // 必须存入 session 或 cookie 校验
}.Encode()
2. 回调处理 /callback(接收 code 和 state):
- 先比对
state防 CSRF - 用
code向https://open.feishu.cn/open-apis/authen/v1/access_tokenPOST 换 token - 注意:Header 必须设
Content-Type: application/x-www-form-urlencoded,Body 是 form-encoded 字符串,不是 JSON
3. 拿到 access_token 后请求用户信息:
req, _ := http.NewRequest("GET", "https://open.feishu.cn/open-apis/authen/v1/user_info", nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
// 注意:飞书要求这个 header 全大写 Bearer,小写 bearer 会 401
session 和 refresh_token 怎么安全存?
Go 原生 net/http 没有内置 session,别硬套 gorilla/sessions 存敏感字段:
state可存在加密 cookie(http.SetCookie+secure/httpOnly标志),过期时间 ≤ 5 分钟refresh_token绝对不能进前端或 cookie,必须落库(如 PostgreSQL 的users.refresh_token字段),且加密存储(推荐golang.org/x/crypto/nacl/secretbox)- 每次用
refresh_token换新access_token后,立即用新refresh_token覆盖旧值——飞书每次刷新都会返回新refresh_token
漏掉最后一点,30 天后用户就得重新扫码登录。
常见 400/401 错误怎么快速定位?
飞书 OAuth 返回错误不友好,优先查这三项:
- 收到
400 {"code":10003,"msg":"invalid app_id or app_secret"}:检查后台填的App ID和App Secret是否复制完整(飞书控制台里带空格或换行易被粘贴进去) - 收到
401 {"code":110001,"msg":"invalid token"}:90% 是Authorizationheader 写成Bearer xxx但 xxx 是过期的 access_token;剩下 10% 是用了 refresh_token 当 access_token 传了 - 回调地址 404:飞书只认你在开放平台「安全设置」里白名单的
redirect_uri,必须完全一致(包括末尾斜杠、http/https、大小写)
飞书调试最麻烦的点不在代码,而在配置项分散在三个地方:开放平台应用页、安全设置页、权限页——少配一个 scope,user_info 接口就返回空数据,但 HTTP 状态码还是 200。