How do I create a custom exception for
org.springframework.security.core.userdetails.UserDetails.getAuthorities()" cannot be invoked because "user" is null
I am creating one but it only sends the exception to the console and does not return in postman
My exception:
package com.msdev.order_controller_api.customException;
public class UserNotExistException extends RuntimeException{
public UserNotExistException(){
super("User not found");
}
}
My handler:
@ExceptionHandler(UserNotExistException.class)
public ResponseEntity handlerUserNotExistException(UserNotExistException exception){
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(exception.getMessage());
}
>Solution :
The @ExceptionHandler annotation doesn’t catch exceptions thrown in the security layer, it just catches the exceptions throw in the controller.
If you want to catch the exceptions thrown by the Filter, the recommended approach is to configure an AuthenticationEntryPoint from the Spring Security. This allows you to returns a customized response when authorization exceptions happens, like when the user is not authenticated or is not authorized.
Here is an example of how to configure a AuthenticationEntryPoint:
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAuthenticationEntryPoint implements
AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Unauthorized");
}
}
And the Spring Security, where you handle the exception using the method .exceptionHandling:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final CustomAuthenticationEntryPoint authenticationEntryPoint;
public SecurityConfig(CustomAuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
// Authorization config
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling(configurer -> configurer.authenticationEntryPoint(authenticationEntryPoint));
// Another configurations...
return http.build();
}
// Another configurations...
}
You can read more about how to handle Spring Security exceptions here.