OAuth Redirect 里常见的 URL 编码问题
OAuth redirect 问题经常来自重复编码、漏编码,以及把外层 query 和内层 URL 混在一起。
OAuth redirect 问题很多时候本质上是 URL 编码问题。身份提供方提示 redirect_uri 不匹配,callback 丢了参数,或者登录后的返回地址被截断,背后常常是编码边界没处理好。
常见原因有三类:漏编码、重复编码,以及编码了错误的层级。
Redirect URI 通常必须精确匹配
身份提供方一般会严格比较 redirect URI。下面这些可能都是不同值:
https://app.example.com/callbackhttps://app.example.com/callback/https://app.example.com/callback?source=loginhttps%3A%2F%2Fapp.example.com%2Fcallback
控制台注册值、授权请求里的值、应用回调路由需要一致。
内嵌 URL 要特别小心
常见模式是登录 URL 里带返回地址:
/login?return_to=/billing?tab=invoices&page=2
内层的 ? 和 & 属于返回地址,不属于外层登录 query。如果不编码,外层解析器会把它们错误拆开。
更安全的形式是编码内层值:
/login?return_to=%2Fbilling%3Ftab%3Dinvoices%26page%3D2
可以用 URL 编码 / 解码工具 分层检查。
留意重复编码
重复编码通常发生在你的代码编码了一次,框架或 HTTP 客户端又编码了一次。
典型信号包括:
- 看到
%253A,但期望的是%3A。 - 看到
%252F,但期望的是%2F。 - 身份提供方展示的 redirect URI 解码一次后仍然带百分号。
调试时一层一层解码。如果解两次才变成人类可读,就去找第二次编码发生在哪里。
空格和加号并不总等价
在 application/x-www-form-urlencoded 中,+ 经常表示空格。一般 URL 百分号编码里,空格是 %20,加号就是字面量加号。
OAuth 参数会经过 form post、URL、日志和 SDK helper。需要明确当前是哪种编码模式。
排查清单
Callback 失败时可以检查:
- 注册的 redirect URI 和请求里的值是否一致。
- 请求值解码一次后是否符合预期。
- 内嵌 URL 是否作为单个参数值编码。
- 是否出现
%25,这通常表示%本身被编码了。 state和nonce是否完整往返。
OAuth 很复杂,但把每一层 URL 分开看,很多 redirect 问题会变简单。