自定义OIDC Callback URL返回404?pac4j+Spring WebFlux问题排查
问题描述
基于spring-webflux-pac4j-boot-demo项目,使用pac4j在Spring Boot + WebFlux环境中实现OIDC认证时,为OIDC客户端设置了自定义Callback URL:http://localhost:8081/api/oidc/cb?client_name=abcd。
访问/authenticate时会正常跳转至IDP提供商完成登录,但登录后重定向到该自定义Callback URL时返回404错误。默认的Callback URL /callback仍可正常工作,向其发送GET请求时,日志明确显示回调逻辑已执行。
疑问:为何调用setCallbackUrl修改Callback URL后不生效?
日志信息
2023-01-15 21:27:04.417 DEBUG 442814 --- [or-http-epoll-3] o.p.core.engine.DefaultCallbackLogic : === CALLBACK === 2023-01-15 21:27:05.995 DEBUG 442814 --- [or-http-epoll-3] o.p.core.engine.DefaultCallbackLogic : foundClient: #OidcClient# |.... ...
当前配置代码(Pac4jConfig.java)
package io.company.auth; import java.util.Optional; import org.pac4j.core.client.Clients; import org.pac4j.core.config.Config; import org.pac4j.core.matching.matcher.PathMatcher; import org.pac4j.springframework.web.SecurityFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.server.WebFilter; import org.pac4j.oidc.client.OidcClient; import org.pac4j.oidc.config.OidcConfiguration; @Configuration // to define the callback and logout controllers @ComponentScan(basePackages = "org.pac4j.springframework.web") public class Pac4jConfig { @Bean public Config config() { OidcConfiguration config = new OidcConfiguration(); config.setClientId("my_client_id"); config.setSecret("my_secret"); config.setDiscoveryURI("idp_dicovery_url"); config.setScope("openid"); config.setUseNonce(false); OidcClient oidcClient = new OidcClient(config); oidcClient.setName("ABCDapp"); oidcClient.setCallbackUrl("http://localhost:8081/api/oidc/cb?client_name=abcd"); final Clients clients = new Clients("http://localhost:8081/api/oidc/cb?client_name=abcd", oidcClient); return new Config(clients); } @Bean public WebFilter protectedFilter() { return SecurityFilter.build(config(), new PathMatcher().includePath("/authenticate")); } }
解决方案
问题核心是:自定义Callback URL没有对应的请求处理器映射。pac4j默认通过org.pac4j.springframework.web中的CallbackController处理/callback路径,但自定义路径/api/oidc/cb并未被配置为pac4j回调逻辑的处理路径,因此返回404。
具体修改步骤
简化Callback URL配置
不需要指定完整的绝对URL,只需设置相对路径即可,pac4j会自动根据请求上下文拼接完整地址。同时避免在OidcClient和Clients中重复配置。添加自定义回调路径的过滤器
新增一个WebFilter,让pac4j的回调逻辑能处理自定义路径的请求。
修改后的配置代码
package io.company.auth; import org.pac4j.core.client.Clients; import org.pac4j.core.config.Config; import org.pac4j.core.matching.matcher.PathMatcher; import org.pac4j.springframework.web.SecurityFilter; import org.pac4j.springframework.web.CallbackFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.server.WebFilter; import org.pac4j.oidc.client.OidcClient; import org.pac4j.oidc.config.OidcConfiguration; @Configuration @ComponentScan(basePackages = "org.pac4j.springframework.web") public class Pac4jConfig { @Bean public Config config() { OidcConfiguration config = new OidcConfiguration(); config.setClientId("my_client_id"); config.setSecret("my_secret"); config.setDiscoveryURI("idp_dicovery_url"); config.setScope("openid"); config.setUseNonce(false); OidcClient oidcClient = new OidcClient(config); oidcClient.setName("ABCDapp"); // 只设置相对路径 oidcClient.setCallbackUrl("/api/oidc/cb"); // Clients构造参数也使用相对路径 final Clients clients = new Clients("/api/oidc/cb", oidcClient); return new Config(clients); } @Bean public WebFilter protectedFilter() { return SecurityFilter.build(config(), new PathMatcher().includePath("/authenticate")); } // 新增:处理自定义回调路径的过滤器 @Bean public WebFilter callbackFilter() { return CallbackFilter.build(config()); } }
补充说明
CallbackFilter是pac4j专门用于处理回调请求的过滤器,它会自动匹配配置中所有客户端的Callback URL路径,无需额外指定路径匹配规则。- 如果需要更精细的路径控制,也可以使用
SecurityFilter并指定回调路径的匹配规则,比如:@Bean public WebFilter callbackFilter() { return SecurityFilter.build(config(), new PathMatcher().includePath("/api/oidc/cb")); }
内容的提问来源于stack exchange,提问作者dCoder
相关产品推荐
相关产品推荐

