这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
第三方账号绑定与最小权限
拿到第三方身份之后
OAuth 流程走完,你的系统拿到了第三方用户信息(比如 GitHub 的 id、login、name)。但登录还没结束——你还需要决定:这个外部身份对应本地哪个账号。
这就是账号绑定要解决的问题。
绑定策略
第一次第三方登录时,通常有三种选择:
| 策略 | 做法 | 适用 |
|---|---|---|
| 自动建号 | 直接创建本地账号并绑定 | 简洁,但可能产生僵尸账号 |
| 绑定引导 | 若邮箱已存在则要求验证后绑定 | 更安全,防账号串绑 |
| 合并选择 | 让用户选择「新建」或「绑定已有」 | 灵活,体验稍重 |
核心原则:openid 不是主键
不要把外部平台的 openid 当成你系统的内部主键。
原因很实际:
- 用户可能绑定多个身份来源(GitHub + 微信 + Google)。
- 外部平台可能删号、改 ID、撤销授权。
- 你的用户数据要跟随你自己的 user_id,而不是外部 ID。
正确的模型是:
user_account(你自己的用户表)
└─> identity_binding
├─ provider: github
├─ external_sub: <github 的用户 id>
└─ user_id: <你的本地用户 id>
identity_binding 只做「外部身份 → 本地用户」的映射,一行一个绑定来源。
绑定要回答的问题
- 第一次第三方登录,自动建号还是引导绑定?
- 如果邮箱已存在,是否允许直接绑定?(直接绑可能被「先注册同邮箱 → 再引导绑定」攻击,通常要验证邮箱归属)
- 用户如何解绑第三方账号?
- 第三方账号被撤销授权后,本地会话如何处理?(降级、要求重新验证)
Scope 与最小权限
OAuth 申请权限时,一个原则贯穿始终:scope 最小化。
- 如果只是登录,不要申请读写仓库、联系人、支付等权限。
- 申请越多,用户越不信任,泄露后风险也越大。
❌ scope=repo,user,notifications,admin:org
✅ scope=read:user (只读用户公开信息)
第三方 access token 要加密存储,并记录来源、过期时间和刷新方式。如果只是登录用途,通常不需要长期保存第三方 token——用完即可,需要时再重新授权。
小结
- 本地系统保留自己的 user_id,外部 openid 只做映射。
- 绑定策略要防「邮箱串绑」攻击。
- scope 最小化,第三方 token 按需保存、加密存储。
- 解绑、撤销授权都要有对应的本地处理。
到这里,登录、Token、会话、SSO、OAuth 都齐了。下一章加最后一块安全拼图:多因素认证 MFA。
发现内容有问题?
告诉我们哪里需要改进。
