Spring Security with basic / error redirection for invalid credentials

I have a spring boot application working with spring security using basic auth. When the correct basic credentials are provided, everything will be fine, but for the wrong credentials for spring authentication, an HttpRequestMethodNotSupportedException: Request method 'POST' not supported exception occurs HttpRequestMethodNotSupportedException: Request method 'POST' not supported .

According to the logs, an authentication error was identified by spring, but that is not what comes out.

2015-08-12 09:33:10.922 INFO 16988 --- [nio-8080-exec-4] osbaaudit.listener.AuditListener : AuditEvent [timestamp=Wed Aug 12 09:33:10 AEST 2015, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}] 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] osweb.servlet.DispatcherServlet : Bound request context to thread: FirewalledRequest[ org.apache.catalina.core.ApplicationHttpRequest@483e1fc6 ] 2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] osweb.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing POST request for [/myapplication/error] 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] osweb.servlet.DispatcherServlet : Testing handler map [ org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@ 331bb032] in DispatcherServlet with name 'dispatcherServlet' 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] oswshandler.SimpleUrlHandlerMapping : No handler mapping found for [/error] 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] osweb.servlet.DispatcherServlet : Testing handler map [org.s pringframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping@ 69e79b9b] in DispatcherServlet with name 'dispatcherServlet' 2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] osweb.servlet.DispatcherServlet : Testing handler map [org.springframework .web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@ 27cc0354] in DispatcherServlet with name 'dispatcherServlet' 2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] swsmmaRequestMappingHandlerMapping : Looking up handler method for path /error 2015-08-12 09:33:10.928 DEBUG 16988 --- [nio-8080-exec-4] .mmaExceptionHandlerExceptionResolver : Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported

In the above logs and after debugging the spring source, I found that after determining that the credentials are incorrect, spring throws a BadCredentials exception and then tries to redirect to "/ error", this redirect is what causes the HttpMethodNotAllowed exception (my application does not has endpoint / error).

I tried to tell spring not to use / error by setting the following,

`the open ServerCustomization class extends ServerProperties {

 @Override public void customize(ConfigurableEmbeddedServletContainer container) { super.customize(container); container.addErrorPages(new ErrorPage(HttpStatus.UNAUTHORIZED, null)); }` 

This will cause spring to stop throwing an HttpMethodnotallowed exception and make it 401 (unauthorized), but my exception will not catch my Exception handler (configured using @ControllerAdvice ).

I also tried setting up a custom entry point for authentication, as shown below, with no luck.

 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { AlwaysSendUnauthorized401AuthenticationEntryPoint alwaysSendUnauthorized401AuthenticationEntryPoint = new AlwaysSendUnauthorized401AuthenticationEntryPoint(); @Override protected void configure(HttpSecurity http) throws Exception { http.headers().httpStrictTransportSecurity().xssProtection().and().authorizeRequests().anyRequest().fullyAuthenticated() .and().csrf().disable(); http.exceptionHandling().authenticationEntryPoint(alwaysSendUnauthorized401AuthenticationEntryPoint); } public class AlwaysSendUnauthorized401AuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public final void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); } } 

}

Is there any way to tell spring not to redirect to / error and return a Bad Credentials exception?

+6
source share
2 answers

I created a sample Spring Boot application with the following security config:

 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("test").password("password").roles("USER"); } @Bean public AuthenticationEntryPoint authenticationEntryPoint() { return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED); } @Override protected void configure(HttpSecurity http) throws Exception { http.headers().httpStrictTransportSecurity().xssProtection() .and().authorizeRequests().anyRequest().fullyAuthenticated() .and().csrf().disable(); http.httpBasic().authenticationEntryPoint(authenticationEntryPoint()); http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint()); } } 

When I enter an invalid username / password (nothing but a test / password), I get the following response:

 {"timestamp":1439381390204,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"} 

This error is returned by the org.springframework.boot.autoconfigure.web.BasicErrorController class, which, if you look, defines two methods with @RequestMapping("/error") - errorHtml and error . Since you are creating an API, this is the second one that needs to be called, and I would say that the "right" behavior!

So, firstly, make sure you get into the BasicErrorController when authentication fails. If so, be sure to use the error NOT errorHtml .

If none of the above questions are helpful, check to see if anyone has changed the default behavior of the error controller. One common (and current) extension is to implement your own org.springframework.boot.autoconfigure.web.ErrorAttributes to change the default payload. But it's just as easy to replace the entire BasicErrorController non-standard implementation, so check this in your application.

If everything else does not work, and you are categorically against wanting to disable Spring's default error handling (which I do not recommend), try adding this to your configuration:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})

What this will do is that error controllers do not load into the application context.

+8
source

I think instead of http.exceptionHandling().authenticationEntryPoint you should use http.httpBasic().authenticationEntryPoint . For form based authentication, this works for me:

 http .formLogin() .failureHandler(authenticationFailureHandler()) ... ... 

You can use Spring SimpleUrlAuthenticationFailureHandler for the authentication failure handler. When creating an instance without any parameter, it will do what we want:

 @Bean public AuthenticationFailureHandler authenticationFailureHandler() { return new SimpleUrlAuthenticationFailureHandler(); } 

This is my complete security configuration file if it helps you.

+1
source

All Articles