When developing REST APIs with the Spring framework and Spring Security, you may encounter a situation where the client provides invalid credentials but the server returns HTTP status 403 Forbidden, which incorrectly conveys the meaning of the error to the client. In such cases, the server should return HTTP status 401 Unauthorized, which better reflects the nature of the error because:

  • HTTP status 403 (Forbidden) indicates that the server understood the request but refuses to authorize it. This status code is used when the client’s credentials are recognized (the user is authenticated), but the client does not have permission to access the resource.
  • HTTP status 401 (Unauthorized) indicates that the client must authenticate itself to get the requested response. This status code is used when the client has not provided credentials, or the provided credentials are invalid.
So, to fix this issue in Spring Security, put the following code in your security configuration class (with Spring Security 5.x or earlier):

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
		...
		.and()
		.exceptionHandling().authenticationEntryPoint(
			(request, response, ex) -> {
				response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
			}					
		);
	}	
	
}
This code ensures that when an authentication error occurs, the application will send HTTP status 401 to the client.

With Spring Security 6.x or later, the configuration code will be slightly different, as shown below:

@Configuration
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    	
    	http.authorizeHttpRequests(...)
    	
    		.exceptionHandling(exh -> exh.authenticationEntryPoint(
			(request, response, ex) -> {
				response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
			}
		))


    	return http.build();    	
    }
}
Note that the authenticationEntryPoint() method accepts an object of a class that implements the AuthenticationEntryPoint interface, which declares the following method:

void commence(HttpServletRequest request, HttpServletResponse response,
		AuthenticationException authException) throws IOException, ServletException;
That means the above configuration code uses Lambda expression as a shortcut to create a class that implement the functional interface AuthenticationEntryPoint. Got it?

That’s how to update Spring Security configuration to return HTTP status 401 instead of 403 in case authentication error occurs, which better reflects the meaning of the status code to the client. I recommend you watch the following video to see the coding in a real-life project:

 

Related Spring Security Articles:

 

Learn more about Spring Security:



 


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Add comment