Spring Authorization Server报错:找不到OAuth2授权码请求令牌的AuthenticationProvider
核心原因
你碰到的ProviderNotFoundException,本质是授权码请求阶段的OAuth2AuthorizationCodeRequestAuthenticationToken令牌没有对应的AuthenticationProvider处理。你的自定义CustomAuthProvider应该是负责用户名密码登录的认证逻辑,但授权码流程需要框架自带的专属处理提供者,而你可能在配置SecurityFilterChain时覆盖了默认提供者,或是没正确注册必要的内置组件。
排查修复步骤
1. 限定自定义AuthProvider的处理范围
检查CustomAuthProvider的supports(Class<?> authentication)方法,确保它只处理用户名密码类型令牌,不要触碰授权码请求令牌的处理逻辑:
@Override public boolean supports(Class<?> authentication) { // 仅处理用户名密码认证 return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); }
2. 保留授权服务器的内置提供者
配置授权服务器的SecurityFilterChain时,不要只添加自定义提供者,要通过authenticationProvider()方法在保留默认授权码相关提供者的基础上,追加自定义组件。正确配置示例:
@Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { // 先应用授权服务器默认安全配置,自动注册授权码流程所需的内置提供者 OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); // 追加自定义认证提供者 http.authenticationProvider(new CustomAuthProvider()); return http.build(); }
注意:不要手动覆盖整个
AuthenticationManager,否则会丢失OAuth2AuthorizationServerConfiguration自动注册的内置提供者。
3. 确保自定义LoginUser的正确封装
如果CustomAuthProvider返回自定义LoginUser作为主体,要保证认证成功后,将其正确封装到UsernamePasswordAuthenticationToken中返回,让框架能识别这个主体:
@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = authentication.getCredentials().toString(); // 自定义逻辑获取LoginUser LoginUser loginUser = customUserService.loadUserByUsername(username); // 密码校验等逻辑... // 返回封装好的认证令牌 return new UsernamePasswordAuthenticationToken(loginUser, password, loginUser.getAuthorities()); }
4. 检查授权端点的权限配置
确保授权码流程的核心端点(/oauth2/authorize、/oauth2/token)没有被自定义安全规则拦截,依赖OAuth2AuthorizationServerConfiguration的默认配置即可保证这些端点的权限正确性。
总结
问题根源是授权码请求阶段的认证令牌缺少对应处理器,核心修复点是保留框架自带的OAuth2授权码相关AuthenticationProvider,同时让自定义CustomAuthProvider只专注于用户名密码认证逻辑,不干扰授权码流程的内置处理。
内容的提问来源于stack exchange,提问作者francissoria

