1

In a spring boot controller I am using @PreAuthorize("isAuthenticated()") to check if the user is logged in(using basic auth + JSESSIONID).
But if the user is not logged in i.e they are not authenticated, the controller returns the 403 Forbidden.
According to what I am known of Authentication vs Authorization, 401 is for Authentication while 403 is for Authorization.

As per my understanding @PreAuthorize() always check the authorization(as the name suggest) of the user, but is there any way to customize this on the basis of argument we pass to it, i.e isAuthenticated() here?

I know there is another solution: using the URL based security configuration in configure(HttpSecurity httpSecurity), but what if I don't want to do it this way.

Any ideas please.

The Coder
  • 3,447
  • 7
  • 46
  • 81

1 Answers1

0

When you annotating method A with @Pre/PostAuthorize than spring will create proxy for such object and each call to such method will go through proxy (if object is under spring context).

The proxy for @Pre/PostAuthorize will evaluate expression from annotation (complicated here) and if it's true than pass the request father (to real method) if not than throw AccessDaniedException. You can also throw such exception by yourself in your method A and the effect will be the same. It's all about how @Pre/PostAuthorize works no more magic here!

But it's not the end of the story!

If AccessDaniedException is not suppressed or retranslated (without stack which doesn't have AccessDaniedException) than it will be catched by ExceptionTranslationFilter in Spring Security and ExceptionTranslationFilter will see if user is Authenticated

  • if yes than ExceptionTranslationFilter will delegate to AccessDeniedHandler to deal with the situation and default implementation of AccessDeniedHandler will return 403 http code or redirect to error page depends if you are using rest or not.

  • if not, than ExceptionTranslationFilter will delegate to AuthenticationEntryPoint and it will deal with the situation (redirect to login page, ask for http basic ... etc).

Note: ExceptionTranslationFilter will rethrow exception if any other than AuthenticationException or AccessDeniedException and probably 500 will be shown :(

Your problem is probably another problem look at Spring Security anonymous 401 instead of 403

Suppressed :(:

    @GetMapping(value = "/test/ok")
    public String getOk() {
        try {
            myService.securedMethod();
            return "ok";
        } catch (Exception e) {
            log.info("AccessDeniedException suppressed not rethrowing :(", e);
            return "error";
        }
    }

Correct retranslated :) :

    @GetMapping(value = "/test/ok")
    public String getOk() {
        try {
            myService.securedMethod();
            return "ok";
        } catch (AccessDeniedException e) {
            throw new MyException(e); //public MyException(Throwable cause)
        }
    }
Andrew Sasha
  • 1,254
  • 1
  • 11
  • 21