Reputation: 344
I have two filters added:
http
.authorizeRequests()
.antMatchers("/cron/**")
.hasAnyRole(APP_ENGINE_CRON, SUPER_ADMIN);
http
.authorizeRequests()
.antMatchers("/**")
.hasAnyRole(SERVICE, SUPER_ADMIN);
http
.addFilterBefore(new AppengineCronRequestHeaderAuthFilter(authenticationManager(), "/cron/**"),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new GoogleIdTokenAuthFilter(authenticationManager(), "/**"),
UsernamePasswordAuthenticationFilter.class);
Configured authentication manager:
@Override protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(appengineCronAuthenticationProvider);
auth.authenticationProvider(googleIdTokenAuthenticationProvider);
}
import com.google.common.base.Strings;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
public class AppengineCronRequestHeaderAuthFilter extends AbstractAuthenticationProcessingFilter {
public static final String X_APP_ENGINE_CRON_HEADER = "X-Appengine-Cron";
public AppengineCronRequestHeaderAuthFilter(AuthenticationManager authenticationManager,
String processingUrl) {
super(processingUrl);
this.setAuthenticationManager(authenticationManager);
}
@Override public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
var appengineCronHeader = request.getHeader(X_APP_ENGINE_CRON_HEADER);
if (!Strings.isNullOrEmpty(appengineCronHeader)
&& Boolean.TRUE.equals(Boolean.valueOf(appengineCronHeader))) {
return getAuthenticationManager().authenticate(new CronAuthentication());
}
return null;
}
}
My understanding is that the first authentication provider which is successful should end the chain and proceed to execute the controller method with the provided authentication. The first filter yields an authentication, then the second filter is executed and yields a null authentication. At this point, the controller method is NOT executed, however, I'm getting a 200 response.
What am I missing here?
Upvotes: 1
Views: 467
Reputation: 344
There were a few problems with my configuration.
AbstractAuthenticationProcessingFilter
does not call chain.proceed(...)
for a null Authentication
. Thus if the first filter did not yield an authentication, the request would be terminated and a 200 would be returned.WebSecurityConfigurerAdapter
includes an exception handling configuration which is required to process AccessDenied
exceptions that result from a lack of permissions after authentication in order for AccessDenied
to terminate the request with a 403
.Upvotes: 1