'@PreAuthorize stops propagating exceptions thrown during evaluation of security checks

I have a controller with several endpoints. Every endpoint is mapped to a service which could return 200 or throw an exception, that is then handled and will return the correct error message.

For example, if a user is not found I throw a UserNotFoundException, which is then caught in the ControllerAdvisor that maps it in a 404 not found.

Everything worked fine, until I added the @PreAuthorize. It looks like this:

@PreAuthorize("@userController.userService.getUser(#userId).username == authentication.principal.name")

The problem is that if getUser throws an exception I get a 500 in place of a 404.

The stack trace looks like this:

java.lang.IllegalArgumentException: Failed to evaluate expression '@userController.userService.getUser(#userId).username == authentication.principal.name'

at ...

Caused by: org.springframework.expression.ExpressionInvocationTargetException: A problem occurred when trying to execute method 'getUser' on object of type ...

at ...

Caused by: UserNotFoundException

So it looks like the problem is caused by the UserNotFoundException, which is not properly re-thrown by the PreAuthorize implementation.

This looks like a typical scenario, but I've researched a lot and I didn't find any solution. How can I get my 404 when a user is not found?



Solution 1:[1]

There's no added benefit of using @PreAuthorize in this case.

Just throw your UserNotFoundException within your business logic and map this exception to a 404 in your ControllerAdvisor like you did before.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stefan Haberl