调用Duende IdentityServer时code_challenge缺失问题解决求助
解决方案
1. 核心问题定位
你的配置存在授权模式不匹配的矛盾:
- 自定义的
/api/login接口实际通过**密码模式(Resource Owner Password Credentials)向Duende获取token,但Spring Security配置中却启用了授权码模式(Authorization Code)**的oauth2Login组件。 - 授权码模式默认要求PKCE(Proof Key for Code Exchange)校验,而你的Spring Boot 2.1.6版本对PKCE的支持不完善;同时Duende端即使关闭PKCE,也会因授权模式不匹配导致请求校验失败。
2. 具体修复步骤
(1)清理Spring Security配置,移除冗余的授权码流配置
你已自定义login接口处理token获取,无需保留oauth2Login组件,仅保留资源服务器的JWT验证逻辑即可:
@Override protected void configure(HttpSecurity http) throws Exception { http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues()) .and() .csrf().disable() .authorizeRequests() .antMatchers("/api/login").permitAll() .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt() .jwtAuthenticationConverter(jwt -> { return new JwtAuthenticationToken(jwt); }); }
(2)修改客户端注册配置为密码模式
将ClientRegistration的授权类型改为密码模式,移除授权码模式专属的redirectUriTemplate:
@Bean public ClientRegistrationRepository clientRegistrationRepository() { ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("custom-oauth") .clientId("clienId") .clientSecret("clienKey") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) // 替换为密码模式 .authorizationGrantType(AuthorizationGrantType.PASSWORD) .scope("report", "common") .tokenUri("http://myIP:5001/connect/token") .userInfoUri("http://myIP:5001/connect/userinfo") .userNameAttributeName("id") .clientName("Custom OAuth2 Client") .build(); return new InMemoryClientRegistrationRepository(clientRegistration); }
(3)同步Duende IdentityServer的客户端配置
在Duende后台调整对应客户端的参数:
- 将Allowed Grant Types添加
password - 设置Client Type为
Confidential - 确保Require PKCE设为
false(密码模式下保密客户端无需PKCE校验)
3. 额外说明
- Spring Boot 2.1.6属于老版本,其OAuth2客户端模块对PKCE的支持存在局限,建议避免在该版本中使用依赖PKCE的授权模式(如面向单页应用的授权码模式)。
- 若后续需使用授权码模式,建议升级Spring Boot到2.2及以上版本,该版本完善了PKCE支持,可避免依赖冲突问题。
内容的提问来源于stack exchange,提问作者WinLord
相关产品推荐
相关产品推荐

