OAuth2.RedirectURL必须与提供方后台配置完全一致,因协议强制校验重定向地址,任何差异(如协议、端口、斜杠)均导致invalid_redirect_uri错误。
Go 标准库的 golang.org/x/oauth2 足够完成主流 OAuth2 授权流程,但直接拼接 redirect_uri、手动处理 state、忽略 PKCE 或混用 token 类型,会导致重定向劫持、CSRF 或 token 泄露。
为什么 oauth2.Config 的 RedirectURL 必须和 OAuth 提供方后台配置完全一致
OAuth2 协议强制校验重定向地址。哪怕多一个斜杠、少一个 https、端口没写全,授权服务器都会拒绝回调并返回 invalid_redirect_uri 错误。
- 开发时用
http://localhost:8080/callback,就一定在 GitHub/GitLab/Google 控制台填这个完整字符串,不能只填/callback - 上线后必须用真实域名(如
https://app.example.com/callback),且 Nginx/Apache 需透传原始 Host 和协议头,否则 Go 服务拿到的r.Host可能是内网地址 - 不要在代码里动态拼
RedirectURL:它应是oauth2.Config初始化时的常量,不是每次请求都算
state 参数不是可选的,必须生成、存储、验证
缺失 state 会让登录流程暴露于 CSRF 攻击——攻击者可诱导用户点击恶意链接,用自己控制的 code 换取用户 session。
- 生成:用加密安全随机数(
crypto/rand.Read)生成 32 字节以上 token,再 base64 编码成字符串 - 存储:存入 HTTP-only + Secure 的临时 cookie,或服务端 Redis(带 TTL,建议 10 分钟)
- 验证:回调时比对 URL 中的
state查询参数与存储值,**严格相等**(不用==做模糊匹配),验证后立即删除
用 Exchange 换 token 时,别漏掉 Context 和错误类型判断
oauth2.Config.Exchange 是阻塞调用,不传 context.Context 会导致超时无法中断;而它返回的 error 不只是网络错误,还可能是 oauth2.RetrieveError(如 invalid_grant),需单独处理。