Search code examples
javaspringspring-bootspring-securityaop

@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

  • 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.