
很多 SaaS 产品都会接 OAuth 登录,比如 GitHub 登录、Google 登录、微信登录、企业账号登录。
OAuth 登录的好处很明显:用户不用重新设置密码,注册路径更短,账号可信度更高。对开发者来说,也能减少密码存储、找回密码和安全策略的负担。
但 OAuth 不是“放一个第三方登录按钮”这么简单。真正稳定的 OAuth 登录,要处理授权流程、回调地址、state 校验、账号绑定、邮箱冲突、token 存储和权限范围。
OAuth 登录的核心,是让用户通过第三方身份提供方确认身份,然后让你的系统创建或登录本地账号。
用户点击“使用 GitHub 登录”,跳转到 GitHub 授权页;用户同意后,GitHub 带着授权码跳回你的回调地址;你的服务端用授权码换取 token,再获取用户资料;最后你的系统根据这些资料登录或创建本地用户。
注意:OAuth 提供的是第三方授权和身份信息,你的产品仍然需要自己的用户体系。不要把“第三方账号”直接当成你系统里唯一的用户模型。
接 OAuth 前,通常要先在第三方平台创建 OAuth App。
你会得到 client_id 和 client_secret,并配置允许的回调地址。回调地址非常关键,因为第三方平台只会把用户带回你配置过的地址。
开发环境和生产环境要分别配置,比如:
开发环境:http://localhost:3000/api/auth/callback/github
生产环境:https://example.com/api/auth/callback/github
不要把生产 secret 写进前端代码,也不要提交到代码仓库。它应该放在服务端环境变量里。
用户点击第三方登录按钮时,你的系统会生成一个授权 URL,并把用户跳转到第三方平台。
这个 URL 通常包含:
client_id
redirect_uri
response_type
scope
state
其中 scope 表示你想获取哪些权限,state 用来防止跨站请求伪造,并在回调时确认请求来自你发起的登录流程。
不要一开始就申请过多权限。只申请登录需要的最小范围,比如基础资料和邮箱。
用户授权后,第三方平台会跳回你的回调地址,并带上授权码和 state。
这时第一件事不是换 token,而是校验 state。你要确认回调里的 state 和你发起登录时保存的 state 一致。
如果 state 不一致,就应该拒绝请求。
很多 OAuth 安全问题不是发生在换 token,而是发生在登录流程被伪造或串改。state 校验是最基础的防线。
授权码不能直接当用户身份使用。你需要在服务端把 code 发给第三方平台,换取访问 token。
这个步骤必须在服务端完成,因为它需要使用 client_secret。如果放在前端,就会泄露密钥。
拿到 token 后,再调用第三方平台的用户信息接口,获取用户 ID、邮箱、头像、昵称等信息。
注意:第三方返回的用户 ID 通常比邮箱更可靠。邮箱可能为空、未验证、会变化,而 provider 用户 ID 更适合做账号绑定标识。
拿到第三方用户信息后,你需要决定本地系统里对应哪个用户。
常见做法是建立一张账号绑定表:
user_id
provider
provider_user_id
provider_email
created_at
updated_at
如果绑定表里已经有这个 provider_user_id,就登录对应用户。如果没有,就根据业务规则创建新用户或绑定到已有用户。
不要只用邮箱直接合并账号。邮箱可能未验证,也可能多个 provider 返回同一个邮箱。自动合并前要非常谨慎。
OAuth 登录最容易出问题的地方,是邮箱冲突。
比如用户之前用邮箱密码注册过账号,现在用 Google 登录,Google 返回同一个邮箱。你是直接合并,还是要求用户先登录原账号再绑定?
更稳妥的做法是:如果邮箱已经存在,但没有绑定这个 provider,就提示用户先用原方式登录,然后在账号设置里绑定第三方登录。
这样可以避免攻击者利用邮箱相同或未验证邮箱抢占账号。
第三方登录成功后,你的系统应该创建自己的登录会话。
不要让前端每次都依赖第三方 token 判断是否登录。第三方 token 是你访问第三方 API 的凭证,不等于你产品内的 session。
你的系统应该有自己的 session、cookie 或 token,用来表示用户已经登录你的产品。
如果你不需要持续访问第三方 API,就不一定要长期保存 access token。
OAuth 接入时,不要为了“以后可能用到”申请大量权限。
权限越多,用户越警惕,审核越复杂,安全风险越大。登录通常只需要用户 ID、邮箱和基础资料。
如果必须保存 token,要加密存储,并明确刷新、过期、撤销和权限变更策略。
对于只做登录的场景,很多时候拿到用户信息后就可以完成本地登录,不需要长期保存第三方 token。
用户可能想解绑某个第三方账号,也可能希望同时绑定 GitHub 和 Google。
账号设置里应该提供绑定、解绑、查看已绑定方式的能力。
但解绑时要注意:如果用户只剩一个登录方式,直接解绑可能导致他无法登录。你要提醒用户先设置密码或绑定另一个登录方式。
登录方式管理,是用户账号安全的一部分。
OAuth 登录出问题时,用户通常只会说“登录失败”。
你需要能查到:用户从哪个 provider 登录,授权是否成功,state 是否通过,换 token 是否成功,邮箱是否返回,账号是否创建或绑定,失败原因是什么。
不要记录敏感 token 明文,但要记录足够的错误上下文。
日志会让 OAuth 排查从猜测变成定位。
可以用下面流程理解:
1. 用户点击第三方登录
2. 生成 state 并保存
3. 跳转到第三方授权页
4. 用户同意授权
5. 第三方回调 redirect_uri
6. 校验 state
7. 服务端用 code 换 token
8. 用 token 获取用户信息
9. 查找或创建本地用户
10. 创建本地 session
11. 跳转回产品页面
这条链路每一步都要可追踪,不能只关注最后是否跳回成功。
OAuth 登录可以显著降低注册门槛,但它同时也是账号安全链路的一部分。
接入时要特别注意回调地址、state 校验、服务端换 token、provider 用户 ID、邮箱冲突、账号绑定和最小权限。
下一篇,我们会以具体平台为例,继续讲:GitHub 登录配置流程。