Doorkeeper PKCE客户端令牌刷新实现及刷新401错误咨询
结合你描述的场景——授权码流程正常跑通,但刷新令牌时返回401,且刷新请求未携带code_challenge,这大概率和Doorkeeper的PKCE配置或客户端类型设置有关,我给你梳理几个排查方向和解决方案:
确认客户端类型配置
你的移动应用属于公共客户端(无法安全存储客户端密钥),请检查Doorkeeper后台中该客户端的类型是否设置为「Public」。如果误设为「Confidential」,刷新令牌时Doorkeeper会要求提供client_secret,但移动应用没法安全持有密钥,自然会返回401。检查Doorkeeper的PKCE配置逻辑
最新版Doorkeeper里,pkce_required_for_public_clients配置仅针对authorization_code授权请求(也就是获取授权码的步骤),默认不会要求refresh_token请求携带PKCE参数。如果你的项目里自定义了Doorkeeper的令牌验证逻辑(比如重载了Doorkeeper::OAuth::RefreshTokenRequest相关方法),可能不小心给刷新请求也加了PKCE校验,导致未带code_challenge时触发401。查看Doorkeeper的详细错误日志
401只是通用状态码,建议去看Doorkeeper的服务器日志,里面会有具体的错误原因(比如invalid_client、missing_required_parameter或者invalid refresh token)。举个例子,如果日志提示missing code_challenge,那说明你的配置或自定义逻辑强制要求刷新请求带这个参数,得调整;如果是invalid refresh token,就要检查令牌是否过期、是否被吊销。确认AppAuth的刷新请求逻辑
AppAuth处理刷新令牌时,默认不会发送PKCE相关参数——这是符合OAuth2规范的,因为PKCE本来就是用于授权码交换阶段的安全验证。如果Doorkeeper配置没有特殊要求,这个行为是正确的,不用修改AppAuth的请求逻辑。
最后给你一个快速验证方案:临时在Doorkeeper配置里关闭pkce_required_for_public_clients,再尝试刷新令牌。如果能成功,说明问题出在PKCE配置的范围覆盖上;如果还是401,就重点排查客户端类型和刷新令牌的有效性。
内容的提问来源于stack exchange,提问作者mazikwyry

