0
votes

My application needs to support only one URL. Like http://.../service/api. The action to be done depends on a "ACTION" request param

To handle this I have created the below controller

@RestController
public class Controller {

@PostMapping(path = "/api", params = "ACTION=INIT")
 public String init() {
   return "Inside Initialize";
 }

 @PostMapping(path = "/api", params = "ACTION=FETCH")
 public String fetch() {
   return "Inside Fetch";
 }
 
 @PostMapping(path="/view", param = "!ACTION")
 public String view() {
   return "Inside View";
 }

The /view will be called when ACTION param is missing. For the first two request I have configured OAuth authentication and the latter i.e. /view will use formlogin.

I have created a filter where I check for the ACTION param and if missing I forward the request to /view handler.

@Component
public class RouteFilter extends OncePerRequestFilter {

  @Override
  protected void doFilterInternal(HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse, FilterChain filterChain)
      throws ServletException, IOException {
    if(!StringUtils.hasText(httpServletRequest.getParameter("ACTION"))){
      httpServletRequest.getRequestDispatcher("/view").forward(httpServletRequest,httpServletResponse);
    }else {
      filterChain.doFilter(httpServletRequest,httpServletResponse);
    }
  }

Below is the Filter Registration. I have made sure that my filter is called before FilterChainProxy

@Autowired
private RouteFilter routeFilter;

@Bean
public FilterRegistrationBean<RouteFilter> filter() {
  FilterRegistrationBean<RouteFilter> bean = new FilterRegistrationBean<>();
  bean.setFilter(routeFilter);
  bean.addUrlPatterns("/api");
  bean.setOrder(-100);
  return bean;
}

Below is the security configuration

@Configuration
@Order(1)
public class Config extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/api")
        .hasAuthority("SCOPE_API")
        .anyRequest()
        .authenticated()
        .and()
        .oauth2ResourceServer()
        .opaqueToken();
  }
}

@Configuration
@Order(2)
public class Config2 extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/view")
        .permitAll()
        .and()
        .formLogin();
  }
}

When I Call /service/api the RouteFilter forwards the request to the /view handler but the Spring Security associated with /view is not honoured. Does Spring Security Filter chain not applicable to forwarded requests or am I missing something here. I am using spring-boot version 2.4.0

1
Isnt it the response that should return a forward to the client… - Toerktumlare
No, the filter chain is not executed again for the forwarded request. If you want to execute the filter chain, you could use redirects instead of forwards. - dur
Thanks @dur. The link you have shared actually helped me to know the root cause. - Mohit Shrivastava

1 Answers

0
votes

As described here we need to add DispatcherType.FORWARD to the springFilterChain to intercept forwarded request. The steps described in the above link didn't work as the springFilterChain was created by SecurityAutoConfiguration. To add forward dispatcher in this we need to set the property in application.yml as

security:
    filter:
      dispatcher-types:
        - request
        - async
        - error
        - forward 

After setting this property request are getting intercepted by the security filter chain.