I have a problem to handle with the exception handling to get 401 Unauthorized result when I don't use bearer token through Postman.
When I use a user bearer token and send a request to this method, I get this response message shown below
{
"time": "2023-05-29T18:06:23.381897147",
"httpStatus": "UNAUTHORIZED",
"header": "AUTH ERROR",
"isSuccess": false
}
I want to get this message shown below as it is a user not admin
{
"time": "2023-05-29T18:06:23.381897147",
"httpStatus": "FORBIDDEN",
"header": "AUTH ERROR",
"isSuccess": false
}
Moreover, I don't use any bearer token,
It always returns 403 Forbidden instead of 401 Unauthorized.
I selected No Auth
from type
part in Authorization
in Postman
and then send a request to the endpoint, handleAccessDeniedError
cannot be called. I think a different exception is used for that.
Which exception should be used?
Here is the relevant part of GlobalExceptionHandler.
@ExceptionHandler({AccessDeniedException.class})
protected ResponseEntity<Object> handleAccessDeniedError(final AccessDeniedException exception) {
log.error(exception.getMessage(), exception);
Error error = Error.builder()
.httpStatus(HttpStatus.FORBIDDEN)
.header(Error.Header.AUTH_ERROR.getName())
.build();
return new ResponseEntity<>(error, HttpStatus.FORBIDDEN);
}
Here is the sample code snippets
@GetMapping
@PreAuthorize("hasAnyAuthority('ADMIN')")
public Response<?> getUsers(@RequestBody @Valid UserListRequest listRequest) {
}
How can I fix the issue?
Here is the solution shown below
1 ) Define CustomAuthenticationEntryPoint
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
/**
* Handles the unauthorized request by sending an "Unauthorized"
* response with the HTTP status code 401 (SC_UNAUTHORIZED).
*
* @param request the {@link HttpServletRequest} object representing the incoming request
* @param response the {@link HttpServletResponse} object used to send the response
* @param authException the {@link AuthenticationException} that occurred during authentication
* @throws IOException if an I/O error occurs while sending the response
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
2 ) Inject CustomAuthenticationEntryPoint
class to SecurityConfiguration
@Configuration
@EnableWebSecurity
@EnableGlobalAuthentication
@EnableMethodSecurity
@RequiredArgsConstructor
class SecurityConfiguration {
....
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity,
AuthenticationFilter authenticationFilter, CustomAuthenticationEntryPoint customAuthenticationEntryPoint){
httpSecurity.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint);
}
.....
}