So I have a simple SecurityFilterChain
configuration and a simple AuthenticationEntrypoint
implementation.
The AutheticationEntrypoint
implementation just writes a JSON response and the send a 403 error to the client.
The problem is that, for some reason, when I try access a protected resource without credentials, the request gets redirected to /error
as I can see in the logs (DEBUG level).
SecurityConfiguration.java
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.formLogin().disable()
.httpBasic().disable()
.csrf().disable()
.headers()
.frameOptions().sameOrigin()
.and()
.exceptionHandling()
.authenticationEntryPoint(new ApplicationAuthenticationEntryPoint())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.build();
}
}
ApplicationAuthenticationEntryPoint.java
public class ApplicationAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final ObjectMapper mapper = new ObjectMapper();
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(mapper.createObjectNode()
.put("timestamp", LocalDateTime.now().toEpochSecond(ZoneOffset.of("-3")))
.put("message", "Access denied to resource")
.toString());
}
}
When I call a protected resource, I see the following in the logs:
2023-03-10T14:59:49.528-03:00 DEBUG 58236 --- [nio-8080-exec-8] o.s.security.web.FilterChainProxy : Securing GET /test
2023-03-10T14:59:49.528-03:00 DEBUG 58236 --- [nio-8080-exec-8] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2023-03-10T14:59:49.529-03:00 DEBUG 58236 --- [nio-8080-exec-8] o.s.security.web.FilterChainProxy : Securing GET /error
2023-03-10T14:59:49.529-03:00 DEBUG 58236 --- [nio-8080-exec-8] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
Why there's a line "Securing GET /error"? The Spring Security filter chain is called twice due to that "redirect". Including the ExceptionTranslationFilter
. I put a breakpoint on the the ExceptionTranslationFilter
and the debugger falls twice on this breakpoint.
Is this /error
that default error page from Spring Boot? If so, how? Since all the security is made on filters, it hasn't reached the MVC stack yet by the time the authentication exception occurs.
Perhaps I'm lacking knowledge on how Spring Security works.
Why is this happening?
ApplicationAuthenticationEntryPoint
is executed. This class is returning an error (response.sendError(HttpServletResponse.SC_FORBIDDEN);
). This error is redirected to/error
(default error handler). You have to permit/error
to see the error response. – CoupBasicErrorController
mapped to /error by default to the servlet container, tomcat in this case. When theSC_FORBIDDEN
is sent in the response, tomcat delegate the global error page to the/error
which then falls to theBasicErrorController
to write the corresponding response. – Weighbridge/error
and you will see the error message. Maybe it is some other exception, I could not see in your code. – Coup