Spring Security UsernamePasswordAuthenticationFilter: How to access Request after a failed login - spring

I am implementing a login page using Angular 7 and Spring Boot and I am with an issued processing a failed login. Basically I want to lock for a specific amount of time the login after X login attempt failures.
HttpSecurity configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("#### Configuring Security ###");
JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(authenticationManager());
jwtAuthenticationFilter.setFilterProcessesUrl("/rest/users/authenticate");//this override the default relative url for login: /login
http
.httpBasic().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/rest/", "/rest/helloworld/**").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint()).and()
.addFilter(jwtAuthenticationFilter);
To process the login i created a Filter
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static Logger logger = Logger.getLogger(JWTAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
//sucessfull authentication stuff
}
#Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
logger.info("Authentication failed");
ErrorMessage errorMessage = new ErrorMessage("access_denied", "Wrong email or password.");
String jsonObject = JSONUtil.toJson(errorMessage);
//processing authentication failed attempt
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
AuthenticationService authenticationService = Application.getApplicationContext().getBean(AuthenticationService.class);
int numFailedAttemptLogin = authenticationService.authenticationFailedAttempt(credentials.getUserName());
response.setStatus(403);
PrintWriter out = response.getWriter();
out.print(jsonObject);
out.flush();
out.close();
//super.unsuccessfulAuthentication(request, response, failed);
}
}
The login is working fine with no issues. My problem is with the unsuccessfulAuthentication method. When the user enters bad credentials, a BadCredentials exception is raised and unsuccessfulAuthenticationmethod is call. Here i need to access again to the request form to extract the username and process the authentication failed attempt and I am getting the following exception
java.io.IOException: Stream closed
This is because inside the attemptAuthentication method the request inputstream is read and obviously closed.
How can i access request body information inside the unsuccessfulAuthentication?
I tried SecurityContextHolder.getContext().getAuthentication() but it is null due the authentication failure.
Does anyone have any idea?
Best Regards

After following M.Deinum suggestion i was able to create a component that listens specific Exceptions:
#Component
public class AuthenticationEventListener implements ApplicationListener<ApplicationEvent> {
private static Logger logger = Logger.getLogger(AuthenticationEventListener.class);
#Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
logger.info(String.format("Event types: %s", applicationEvent.getClass()));
if (applicationEvent instanceof AbstractAuthenticationFailureEvent) {
String username = ((AbstractAuthenticationFailureEvent) applicationEvent).getAuthentication().getName();
if (applicationEvent instanceof AuthenticationFailureBadCredentialsEvent) {
logger.info(String.format("User %s failed to login", username));
//this.handleFailureEvent(username, event.getTimestamp());
}
}
}
}
This approach is using Exceptions to drive what to do in specific scenarios. I was able to achieve something similar keep using my JWTAuthenticationFilter like this
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
try {
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (BadCredentialsException bce) {
try {
handleBadCredentials(credentials, response);
throw bce;
} catch (LockedException le) {
handleUserLocked(credentials, response);
throw le;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
logger.info("Authentication failed");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.getWriter().print(authException.getLocalizedMessage());
response.getWriter().flush();
}
Thak you all for your time and help, much appreciated.

Related

Catching CharConversionException in Spring Boot

I have a typical JWT authentication process on my app. I am able to catch most of the token errors, but when the user sends a bad bearer token (ex. ads.asd.d), CharConversionException is being thrown.
java.io.CharConversionException: Not an ISO 8859-1 character: [�]
The issue is that I can't catch it. I am getting this error.
exception java.io.CharConversionException is never thrown in body of corresponding try statement
Filter class:
public class JwtRequestFilter extends OncePerRequestFilter {
#Autowired
private MyUserDetailsService userDetailsService;
#Autowired
private JwtUtil jwtUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException, MalformedJwtException, CharConversionException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
try {
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
} catch (MalformedJwtException e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
} catch (CharConversionException e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
...
chain.doFilter(request, response);
}
Any idea on how I can catch that exception?

spring-boot Error: Exceeded maxRedirects. Probably stuck in a redirect loop

I am trying to perform JWT auth in spring boot and the request are getting stuck in redirect loop.
JWTAuthenticationProvider
#Component
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
#Autowired
private JwtUtil jwtUtil;
#Override
public boolean supports(Class<?> authentication) {
return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
}
#Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
}
#Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
String token = jwtAuthenticationToken.getToken();
JwtParsedUser parsedUser = jwtUtil.parseToken(token);
if (parsedUser == null) {
throw new JwtException("JWT token is not valid");
}
UserDetails user = User.withUsername(parsedUser.getUserName()).password("temp_password").authorities(parsedUser.getRole()).build();
return user;
}
JwtAuthenticationFilter
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super("/**");
this.setAuthenticationManager(authenticationManager);
}
#Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return true;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith("Bearer ")) {
throw new JwtException("No JWT token found in request headers");
}
String authToken = header.substring(7);
JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken);
return getAuthenticationManager().authenticate(authRequest);
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}
}
SecurityConfiguration
#Configuration
#EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/secured-resource-1/**", "/secured-resource-2/**")
.hasRole("ADMIN").antMatchers("/secured-resource-2/**").hasRole("ADMIN").and().formLogin()
.successHandler(new AuthenticationSuccessHandler()).and().httpBasic().and().exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler()).authenticationEntryPoint(getBasicAuthEntryPoint())
.and()
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()),
FilterSecurityInterceptor.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
return new CustomBasicAuthenticationEntryPoint();
}
}
MainController
#RestController
public class MainController {
#Autowired
private JwtUtil jwtUtil;
#GetMapping("/secured-resource-1")
public String securedResource1() {
return "Secured resource1";
}
}
When I hit the endpoint with the valid JWT token, the code goes in a loop from Filter to provider class and ends in Error:
Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:8000/ error.
Debug logs shows the following error:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Cannot call sendError() after the response has been committed] with root cause
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
Any suggestions what am I missing here.
Thanks in advance.
I believe the the reason for this is because you have not actually set the AuthenticationSuccessHandler for the bean JwtAuthenticationFilter, since it is not actually set it will keep looping around super and chain and later when the error needs to be sent since response is already written in super() chain.doFilter will fail because once the response is written it cannot be again written hence the error call sendError() after the response has been committed.
To correct this in your SecurityConfiguration before setting this
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()),
FilterSecurityInterceptor.class)
Instantiate the filter and set it's success manager like so
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager()),FilterSecurityInterceptor.class);
jwtAuthenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
Now use the above variable to set the filter.
This is a great reference project: https://gitlab.com/palmapps/jwt-spring-security-demo/-/tree/master/.
I solved this problem with another approach.
In the JwtAuthenticationFilter class we need to set authentication object in context and call chain.doFilter. Calling super.successfulAuthentication can be skipped as we have overridden the implementation.
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
//super.successfulAuthentication(request, response, chain, authResult);
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super("/**");
this.setAuthenticationManager(authenticationManager);
//this.setAuthenticationSuccessHandler(new JwtAuthenticationSuccessHandler());
}

How does Spring Security Filter Work With Custom Authentication and How To Combine It with Servlet Filter?

So I have a question regarding Spring Security. So I want to check authentication using custom header which then I want to check the token given in the custom header to redis value and set the data object as credentials at custom implementation of abstract authentication token.
I have already followed the tutorial in this web: https://shout.setfive.com/2015/11/02/spring-boot-authentication-with-custom-http-header/, but I can't update the authentication interface in SecurityContextHolder.getContext() (I set the credentials in my implementation of Authentication Interface, but when I get it in the service, the credentials is null).
I also found other problems, I actually want to order the filter like this:
ExceptionHandlerFilter (to catch exception error in the filter) -> Other filter or CustomWebSecurityConfigurerAdapter.
But when the url matches the antMatcher, I found that ExceptionHandlerFilter was skipped by the application.
I was so confused by this and could not find better tutorial in implementing custom authentication using Spring Security. So I want to ask whether you guys can tell me how Spring Security works and how to combine it with Filter?
Here is my first filter to catch exception
#Component
#Order(0)
public class ExceptionHandlerFilter extends OncePerRequestFilter {
private JaminExceptionHandler exceptionHandler;
private ObjectMapper objectMapper = new ObjectMapper();
#Autowired
public ExceptionHandlerFilter(JaminExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (Throwable exception) {
ResponseEntity<?> responseEntity = this.exceptionHandler.handleException(exception, request);
response.setStatus(responseEntity.getStatusCode().value());
response.setHeader("Content-Type", "application/json");
response.getWriter().write(this.objectMapper.writeValueAsString(responseEntity.getBody()));
}
}
}
Here is my Auth Filter
#Component
public class AuthFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader("J-Auth");
if (token != null) {
Authentication auth = new JaminAuthenticationToken(token);
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
} else {
throw new JaminException("Not authorized", JaminExceptionType.NOT_AUTHORIZED, HttpStatus.UNAUTHORIZED);
}
}
}
Authentication Provider
#Component
public class JaminAuthenticationProvider implements AuthenticationProvider {
private RedisTemplate<String, String> authRedis;
private ObjectMapper objectMapper = new ObjectMapper();
#Autowired
public JaminAuthenticationProvider(#Qualifier("authRedis") RedisTemplate<String, String> authRedis) {
this.authRedis = authRedis;
}
private UserDTO getUserDTO(String token) throws IOException {
String userData = this.authRedis.opsForValue().get(token);
if (userData == null) {
throw new JaminException("Not authorized", JaminExceptionType.NOT_AUTHORIZED, HttpStatus.UNAUTHORIZED);
}
return this.objectMapper.readValue(userData, UserDTO.class);
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
JaminAuthenticationToken auth = (JaminAuthenticationToken) authentication;
try {
UserDTO userDTO = this.getUserDTO(auth.getToken());
auth.setCredentials(userDTO);
return auth;
} catch (IOException e) {
e.printStackTrace();
}
throw new JaminException("Not authorized", JaminExceptionType.NOT_AUTHORIZED, HttpStatus.UNAUTHORIZED);
}
#Override
public boolean supports(Class<?> authentication) {
return JaminAuthenticationToken.class.isAssignableFrom(authentication);
}
}
WebSecurityConfigurerAdapter
#Configuration
#EnableWebSecurity
#Order(1)
public class JaminSecurityAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private JaminAuthenticationProvider jaminAuthenticationProvider;
private void disableDefaultSecurity(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.csrf().disable();
http.formLogin().disable();
http.logout().disable();
http.httpBasic().disable();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
this.disableDefaultSecurity(http);
http.antMatcher("/auth/check")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.addFilterBefore(new AuthFilter(), BasicAuthenticationFilter.class);
// http.authorizeRequests().anyRequest().permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jaminAuthenticationProvider);
}
}
Spring Security has some "before and after" steps. There are a few Handlers that can help. I don't know your code, but if you can get your authentication ok, maybe you just have to extend a SuccessHandler and set the authentication there, like i did in my blog project:
if(checkEmail(authentication)) {
val adminRole = SimpleGrantedAuthority("ROLE_ADMIN")
val oldAuthorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities()
val updateAuthorities = mutableListOf<GrantedAuthority>()
updateAuthorities.add(adminRole)
updateAuthorities.addAll(oldAuthorities)
SecurityContextHolder.getContext().setAuthentication(UsernamePasswordAuthenticationToken(authentication.getPrincipal(),
authentication.getCredentials(),
updateAuthorities))
}
And about the filters, maybe you can find your answer here. I don't like using filters and interceptors, but sometimes they are really necessary.

AuthenticationException thrown in AuthenticationProvider is mapped to AccessDeniedException in ExceptionTranslationFilter

Having written a custom AuthenticationProvider (which calls a service, after which that one calls an external URL to authenticate the given credentials), I wanted to customize the error message people get when their authentication fails, based on the message I pass to the instance of AuthenticationException (so the e.getMessage() passed to BadCredentialsExceptoin in the code below).
#Component
public class TapasAuthenticationProvider implements AuthenticationProvider {
#Override
public TapasAuthentication authenticate(Authentication authentication) throws AuthenticationException {
String userName = authentication.getName();
String password = authentication.getCredentials().toString();
try {
AuthenticationResponse authResponse = authenticationService.authenticate(userName, password);
return new TapasAuthentication(mapToAuthenticatedUser(authResponse, userName, password), password);
} catch (AuthenticationFailedException e) {
// Note that AuthenticationFailedException is a self-written exception, thrown by the authenticationService.
log.error("Authentication failed: ", e);
throw new BadCredentialsException(e.getMessage());
}
}
}
Now I looked up how to map AuthenticationExceptions and found that an AuthenticationEntryPoint should be used for this. So I created one and added it to my SecuritySetup:
#Component
public class TapasAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
System.out.println(authException.getMessage());
// More code to be added once exception is what I expect.
}
}
#Autowired
private TapasAuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests().anyRequest().authenticated().and().httpBasic()
.and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}
This successfully triggers the AuthenticationEntryPoint, but instead of a BadCredentialsException, I get an InsufficientAuthenticationException. I checked the origin of this exception and it comes from the ExceptionTranslationFilter's handleSpringSecurityException. Here the exception turns out to be an AccessDeniedException instead of an AuthenticationException.
private void handleSpringSecurityException(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, RuntimeException exception)
throws IOException, ServletException {
if (exception instanceof AuthenticationException) {
// I would except to enter this if-statement, but exception is not what I expect
sendStartAuthentication(request, response, chain,
(AuthenticationException) exception);
}
else if (exception instanceof AccessDeniedException) {
....
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
// Instead code comes here, and creates an InsufficientAuthenticationException.
sendStartAuthentication(
request,
response,
chain,
new InsufficientAuthenticationException(
messages.getMessage(
"ExceptionTranslationFilter.insufficientAuthentication",
"Full authentication is required to access this resource")));
}
...
}
}
Why does the exception not match my exception thrown in the AuthenticationProvider? And how would I be able to pass data from the AuthenticationProvider back to the user?
Turns out the HttpBasicConfigurer returned by the .basicSecurity() call also allows to register an AuthenticationEntryPoint. When registering it that way, the exception thrown by the Provider does end up in the entry point.
Security config looks like this:
#Autowired
private TapasAuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}

PreAuthorize error handling

I'm using Spring Oauth2 and Spring Pre-post Annotations With Spring-boot
I Have a service class MyService. one of MyService methods is:
#PreAuthorize("#id.equals(authentication.principal.id)")
public SomeResponse getExampleResponse(String id){...}
can i control in some manner the json that is returned by the caller Controller?
the json that is returned by default is:
{error : "access_denied" , error_message: ".."}
I Want to be able to control the error_message param. I'm looking for something similar to:
#PreAuthorize(value ="#id.equals(authentication.principal.id)", onError ="throw new SomeException("bad params")")
public SomeResponse getExampleResponse(String id){...}
One way i thought of doing it is by Using ExceptionHandler
#ExceptionHandler(AccessDeniedException.class)
public Response handleAccessDeniedException(Exception ex, HttpServletRequest request){
...
}
but i can't control the message of the exception. and also i can't be sure that this Exception will be thrown in future releases
Spring Boot docs on error handling: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling. One way you can control the JSON is by adding a #Bean of type ErrorAttributes.
#Bean
ErrorAttributes errorAttributes() {
return new MyErrorAttributes();
}
Implement AccessDeniedHandler
#Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
SomeJsonModel jsonResponse =new SomeJsonModel();
mapper.writeValue(response.getOutputStream(), jsonResponse);
} catch (Exception e) {
throw new ServletException();
}
}
SomeJsonModel will be your own POJO/model class which you can control
And add that access denied handler in Resource Server Configuration
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers(SECURED_PATTERN).and().authorizeRequests()
.antMatchers(HttpMethod.POST,SECURED_PATTERN).access(SECURED_WRITE_SCOPE)
.anyRequest().access(SECURED_READ_SCOPE).and()
.exceptionHandling().authenticationEntryPoint(newAuthExceptionEntryPoint())
.accessDeniedHandler(new MyAccessDeniedHandler());
}
It was not working for me when I implemented AccessDeniedHandler. So I created a ExceptionHandler function inside AuthenticationEntryPoint and marked the class as
#ControllerAdvice.
Please find the code below
#ControllerAdvice
#Component
public class EmrExceptionHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(EmrExceptionHandler.class);
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_AUTHORIZED)));
}
#ExceptionHandler(value = {AccessDeniedException.class})
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AccessDeniedException accessDeniedException) throws IOException {
logger.error("AccessDenied error: {}", accessDeniedException.getMessage());
httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_PERMITTED)));
}
public String convertObjectToJson(Object object) throws JsonProcessingException {
if (object == null) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
}

Resources