← 全部笔记

概念笔记 · 入门

OAuth不只是一个登录按钮

OAuth让用户把一部分、可撤回的访问权交给应用,而不必把自己的平台密码交出去;登录按钮只是这段授权关系的入口。

三幕 · 更新于 2026-09-06 · 初识

内容审阅稿 · 待确认后发布

文章目录

先想象一张门卡

你住在一栋公寓里。现在请清洁人员进来,但你不想把家门钥匙、保险箱钥匙和整栋楼的总钥匙都交给他。你给他一张门卡:只在今天下午有效,只能打开客厅,而且你可以随时让它失效。

OAuth解决的就是这类问题。

用户不把飞书密码交给拾时。用户去飞书自己的页面,同意拾时在有限范围内做某些事。飞书随后给拾时一份代表这次许可的凭据。许可可以有范围,会过期,也可以被撤回。

这个门卡类比有边界。数字Token可以被复制,不像一张实体卡只能在一个人手里,所以保存和日志泄露会更加危险。但它保留了最重要的特征:有限权限、有限时间、可以撤销。

OAuth首先解决的是授权,不是按钮,也不是密码搬家。

十秒演示:把四个角色摆在桌上

拿四张纸,分别写:

你|拾时|飞书授权服务|飞书日历

下面是授权码流程的教学示意,不代表拾时已获得飞书日历权限。按顺序移动一枚硬币:

  1. 拾时请你去飞书授权服务。
  2. 你在飞书确认允许哪些权限。
  3. 飞书把一个短时授权码带回拾时。
  4. 拾时的服务器用授权码换Access Token。
  5. 拾时拿Token去请求飞书日历。
  6. 飞书日历检查Token,合法才返回数据或执行操作。

硬币从来不需要变成你的飞书密码。RFC 6749定义的核心关系也是:客户端获得代表资源所有者授权的许可,再用它换取Access Token,最后携带Token访问受保护资源。

如果你的流程图里只有“用户→拾时”两张纸,那就没有把OAuth搞清楚。

登录和授权不是一回事

登录回答:“你是谁?”

授权回答:“你允许这个应用做什么?”

有些平台会在OAuth流程中同时提供用户身份信息,所以产品界面常写“使用飞书登录”。这句话方便,但容易把两件事揉在一起。

知道用户的飞书身份,不等于拥有日历读取权;能够读取日历,不等于能够修改或删除。实际能力由用户同意的Scope决定。

如果页面把通讯录、消息、日历等所有权限都解释成“登录所需”,那不是简化说明,而是在掩盖事实。

回调地址为什么不能凭感觉填写

授权完成后,飞书需要把浏览器送回拾时。这个返回位置叫回调地址。平台通常会把请求中的地址与后台登记内容比较。

协议、域名、端口和路径共同决定它是不是同一个地址:

http://localhost:3000/callback
https://example.com/callback
https://example.com/oauth/callback

这三个不是同一个地方。

本地、测试和正式环境需要分别规划,不能在上线当天临时改一个域名,就期待所有环节自动正确。拾时正式接入前还要以飞书开放平台当时的回调匹配规则为准。

state到底在防什么

别背“防CSRF”这句话。做个小实验。

同时打开两个浏览器窗口。窗口A从拾时开始飞书授权,窗口B也开始一次授权。如果回调回来后,应用无法判断结果属于哪次开始,就可能把错误的返回与当前会话绑在一起。

如果流程使用state保护这次往返,应用会在开始前生成一段短时、不可预测的值,把它与当前会话绑定;回调时必须比较。对不上,就停止。当前OAuth安全最佳实践也允许在满足条件时由PKCE或OpenID Connect的nonce承担相应保护,具体选择不能脱离平台支持和实际流程。

它像寄存物品时拿到的号码牌。工作人员不能因为你站在柜台前,就随便把一个包递给你。号码不对,事情到此为止。

PKCE又在检查什么

state主要帮助应用确认“回来的是不是我开始的那次流程”。PKCE再增加一组只属于本次授权的配对信息。

应用开始授权时临时生成一个秘密,只把经过变换的结果交给授权服务;稍后兑换授权码时,再交出原始秘密。两者对不上,授权码就不能被兑换。这样即使授权码被截获,拿到它的人也缺少另一半配对信息。

2025年的OAuth安全最佳实践要求公开客户端使用PKCE,并推荐机密客户端也使用。它还要求回调地址原则上进行精确字符串匹配。拾时最终怎样组合state、PKCE或OpenID Connect能力,必须以飞书平台当前支持和应用形态为准,不能照抄一个通用流程图。

授权码、Access Token和Refresh Token不是三种叫法

把三者都叫“Token”然后混在同一字段里,是记住了名词却没弄清用途。

在本文讨论的带后端Web应用中,授权码由服务器换取Token。平台应用密钥不能放进前端。完整Token也不应进入页面、分析事件、普通日志或错误提示。

拿到Token不是完成,而是承担责任:谁能读取、何时过期、怎样刷新、用户撤销后怎样停止、删除账户时怎样清理,都需要答案。

做个反例:回调成功,仍然可能是严重错误

假设用户成功从飞书跳回拾时,页面也显示了他的头像。能宣布接入完成吗?不能。

再做四个实验:

  1. 用户拒绝日历权限,应用会不会仍然显示同步成功?
  2. Token过期后,应用会不会陷入无限重试?
  3. 用户撤销授权后,旧Token还能不能继续访问?
  4. 两个不同用户登录时,日历会不会错绑?

第4个最危险。平台昵称和邮箱可能变化,也不一定唯一。应用需要使用平台提供的稳定标识,并明确它属于哪个平台、哪个应用配置和哪个本地用户。

OAuth流程跑通,只证明硬币走完了路线。它不证明账户关联正确。

权限越多,风险越大

如果拾时只需要识别用户并管理日程,就不应该顺手申请通讯录、聊天消息或其他无关权限。

最小权限不是礼貌,是限制事故范围。门卡丢了,只能打开客厅,总比能打开整栋楼好。

页面还应该分别解释:哪些权限用于识别身份,哪些用于读取日历,哪些用于写入或删除。用户要知道自己交出了什么。

怎样验证理解

下面这些现象不能证明OAuth安全:

真正的检查是拒绝、过期、撤销、重复回调和多用户隔离。如果只演示一次顺利登录,那就像只测试门卡能开门,却从不测试它能不能打开不该开的门。

你真的搞清楚了吗

不用术语回答:

  1. 为什么拾时不应该向用户索要飞书密码?
  2. 已经知道用户是谁,为什么仍不一定能访问日历?
  3. 授权码和Access Token分别用在哪里?
  4. state或PKCE配对信息对不上时,为什么必须停止?
  5. 用户撤销授权后,系统应该发生什么?
  6. 怎样证明两个用户的日历没有错绑?

可以结合拒绝授权、过期和账户错绑的例子,检查每个环节的作用。

我现在知道什么,还不知道什么

我现在能确定:OAuth建立的是一段有限、会过期、可撤回的授权关系。成功回调只是中间一步,不是验收终点。

截至2026年8月28日的记录,拾时已有OAuth登录、state与PKCE代码,但真实扫码、正式回调和用户级日历授权尚未验收。具体Scope、Token生命周期和日历权限仍需平台配置与真实测试确认。本文不是飞书接入成功复盘。

资料与验证范围