集成WebAuthn4J与Spring OAuth2时客户端出现authorization_request_not_found异常
问题场景
基于spring-boot-starter-oauth2-authorization-server和webauthn4j-spring-security-core搭建OAuth2授权服务器,客户端采用authorization_code授权类型。用户名密码登录可正常完成OIDC流程、交换access_token;但WebAuthn登录时,虽验证通过并返回授权码和state,客户端却抛出org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found]异常,排查发现WebAuthn登录后客户端会话中找不到OAuth2AuthorizationRequest,用户名密码登录时该请求存在,修改域名无法解决。
可能的原因及修复方案
1. WebAuthn认证会话与授权请求会话不匹配
Spring Authorization Server在授权请求阶段会将OAuth2AuthorizationRequest存入会话,用户名密码的表单登录流程会自动复用该会话;但WebAuthn认证如果使用独立的SecurityFilterChain或会话配置,可能导致认证后的会话和授权请求的会话不一致,从而丢失授权请求信息。
修复:
- 确保WebAuthn的SecurityFilterChain与OAuth2授权服务器的FilterChain共用同一套会话配置,统一设置
sessionManagement(),避免多会话隔离。 - 确认WebAuthn认证成功后的跳转逻辑:必须跳转回原授权请求的回调端点(如
/oauth2/authorize的回调路径),且携带原请求的state参数,让Spring Security能从正确的会话中加载授权请求。
2. WebAuthn认证过程中会话重置导致授权请求丢失
WebAuthn4J Spring Security的认证流程可能触发会话固定保护(session fixation),导致原会话被销毁或迁移,但未同步OAuth2AuthorizationRequest属性。
修复:
- 在WebAuthn认证的成功处理器中,手动保留会话中的授权请求:
// 获取原授权请求 OAuth2AuthorizationRequest authRequest = (OAuth2AuthorizationRequest) request.getSession() .getAttribute(OAuth2AuthorizationRequestRedirectFilter.AUTHORIZATION_REQUEST_ATTR_NAME); // 认证成功后确保属性仍在会话中 if (authRequest != null) { request.getSession().setAttribute(OAuth2AuthorizationRequestRedirectFilter.AUTHORIZATION_REQUEST_ATTR_NAME, authRequest); } - 调整会话固定保护策略,若开启
migrateSession,需手动复制授权请求属性到新会话:.sessionManagement(session -> session .sessionFixation().migrateSession() .sessionAuthenticationStrategy((auth, req, res) -> { // 复制授权请求到新会话 Object authReq = req.getSession().getAttribute(OAuth2AuthorizationRequestRedirectFilter.AUTHORIZATION_REQUEST_ATTR_NAME); if (authReq != null) { req.getSession().setAttribute(OAuth2AuthorizationRequestRedirectFilter.AUTHORIZATION_REQUEST_ATTR_NAME, authReq); } }) )
3. 会话存储配置不一致
若WebAuthn和OAuth2流程使用不同的会话存储(如分布式会话配置差异),或会话超时时间过短,会导致授权请求在WebAuthn认证过程中丢失。
修复:
- 统一WebAuthn与OAuth2流程的会话存储配置(如Redis、JDBC),确保参数一致。
- 延长授权请求相关会话的超时时间,避免认证过程中会话过期。
4. SecurityFilterChain顺序错误
如果WebAuthn的FilterChain优先级高于OAuth2授权服务器的FilterChain,可能导致授权请求还未存入会话就进入WebAuthn认证,或认证后无法匹配授权端点逻辑。
修复:
- 调整FilterChain顺序,让OAuth2授权服务器的FilterChain(匹配
/oauth2/**等端点)优先级更高。例如给OAuth2链设置@Order(Ordered.HIGHEST_PRECEDENCE + 10),WebAuthn链的顺序稍低。
内容的提问来源于stack exchange,提问作者user28083987

