Skip to content

@PreAuthorize should not apply method security to inherited concrete methods #15352

Closed
@MartinHaeusler

Description

@MartinHaeusler

Describe the bug
I don't know the exact spring security patch version where this behavior changed, but in 6.2.4 I had a setup like this:

@RestController
@PreAuthorize("hasAdminRole()") // expression doesn't matter
public class MyRestController {

    @ResponseBody
    @GetMapping("/status")
    public String someEndpoint(){
        return "foo";
    }

   @ExceptionHandler
   public ResponseEntity<String> handleAccessDeniedException(ServletRequets request, AccessDeniedException e){
        // .... build some nice string... 
   }

}

In Spring Security 6.2.4, if an request comes in that does not match the @PreAuthorize condition, then Spring Security creates an AccessDeniedException, and hands it over to the handleAccessDeniedException(...) method. Everything was fine.

In Spring Security 6.3.1 (and maybe earlier as well, not sure, this is the version I'm currently upgrading to), something else happens:

  • The REST call comes in
  • The @PreAuthorize expression is evaluated and fails
  • An AccessDeniedException is created
  • Spring Security attempts to call handleAccessDeniedException...
  • ... but gets intercepted by the method security again
  • ... which again throws an AccessDeniedException
  • ... which causes the original handler invocation to fail, logging the second AccessDeniedException as a warning with "Failure in @ExceptionHandler handleAccessDeniedException"

Overall, this results in a HTTP 403 for the client, no matter what the handleAccessDeniedException method would have done, because it never gets called.

The workaround is to move all @ExceptionHandler methods to an external @ControllerAdvice class, as those are not subject to the method security imposed by the class-level @PreAuthorize annotation. In Spring Security 6.2.4 this worked out of the box.

I think this is a weird breaking change and a potential pitfall for developers. Nobody would think that spring would intercept itself, applying method security on an exception handler method.

Metadata

Metadata

Assignees

Labels

in: coreAn issue in spring-security-coretype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions