使用Spring Authorization Server时,是否需保存OAuth2AuthorizationRequest?
核心结论
必须保存OAuth2Authorization中的OAuth2AuthorizationRequest属性,这是Spring Authorization Server授权码流程的强制要求,不是操作错误。
原因分析
授权码流程中,/token端点兑换令牌时,CodeVerifierAuthenticator需要通过OAuth2Authorization获取生成授权码时的原始授权请求信息(包括PKCE的code_challenge、请求的redirect_uri、state等参数),用来验证客户端提交的code_verifier是否合法。这些信息都封装在OAuth2AuthorizationRequest对象中,作为OAuth2Authorization的属性存储。如果不保存这个属性,必然会在验证阶段抛出NullPointerException。
解决办法
完整存储
OAuth2Authorization的属性
自定义OAuth2AuthorizationService时,不要只存储客户端、授权类型等基础字段,必须将OAuth2Authorization.getAttributes()中的所有内容序列化后存储(比如用JSON格式存在数据库的attributes字段),读取时再反序列化为原对象。框架默认的InMemoryOAuth2AuthorizationService就是完整存储所有属性的,你可以参考它的实现逻辑。不推荐的替代方案(风险高)
如果坚持不想存储授权请求,需要自己重写CodeVerifierAuthenticator的逻辑,跳过对OAuth2AuthorizationRequest的依赖,但这会破坏框架的安全校验流程,可能导致PKCE验证失效,带来安全隐患,不建议这么做。
关于构建OAuth2AuthorizationRequest的问题
你尝试从数据库获取授权后新建OAuth2AuthorizationRequest的思路不可行:
- 授权请求中的
code_challenge、redirect_uri等参数都是每个请求动态生成的,硬编码或模拟构建会导致验证不通过; - 框架的
OAuth2AuthorizationRequest.Builder确实是针对授权码类型设计的,无法适配其他授权类型的场景,强行使用会导致流程异常。
内容的提问来源于stack exchange,提问作者Shivesh Kaundinya

