Spring Security has replaced the two classes AccessDecisionManager and AccessDecisionVoter by the AuthorizationManager. Very nice. Unfortunately, the Spring Security team once again, as usual, did not think of providing newbies with useful examples. Why should they. It seems to be enough to say that it is done differently now. How exactly, is left to the newbie to find out in countless hours. The rabble has enough time anyway. And the pros know how it works for sure...
I want to implement an AuthorizationManager, which extends the current Spring Security decision logic with a custom voter. This voter shall decide as last instance with the help of ConfigAttributes, if an AccessDeniedException or an AuthorizationException is thrown (at least in legacy examples these exceptions were used to determine whether the authentication process is started or the AccessDeniedHandler is called).
To be a little more precise:
I want to annotate methods with the permission that calling these methods/endpoints will start the login process if the user is not logged in. Anything else will automatically result in a 404.
For the legacy classes there are enough examples to find on the internet. But for the new ones nothing - nothing at all :(. Can anyone please tell me where I can find examples for the implementation of a custom AuthorizationManager that takes the existing voter into account and implements my own voter as well?
Many thanks in advance
I know this is a few months old, but I haven't seen the answer elsewhere, so I'm going to share what I've found:
As I read the new docs, it looks like you chain access(AuthorizationManager<T> authorizationManager) into your requestMatchers() call for the URL pattern. AuthorizationManager<T> is an interface with two methods:
default void verify(Supplier<Authentication> authentication, T object)
Determines if access should be granted for a specific authentication and object.
Parameters:
authentication - the Supplier of the Authentication to check
object - the AuthorizationManager object to check
Throws:
AccessDeniedException - if access is not granted
@Nullable
AuthorizationDecision check(Supplier<Authentication> authentication, T object)
Determines if access is granted for a specific authentication and object.
Parameters:
authentication - the Supplier of the Authentication to check
object - the AuthorizationManager object to check
Returns:
an AuthorizationDecision or null if no decision could be made
Extend AuthorizationManager with your logic in the access(...) and verify(...) methods, chain it to your RequestMatcher logic, and that looks like it.
To understand how this fits in to the current architecture look here: https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html#request-authorization-architecture
As a quick summary, the default last step in the SecurityFilterChain is the AuthorizationFilter, which gets the current Authentication from the SecurityContext and passes it to an AuthorizationManager. The authorization manager can perform whatever logic you want to make the authorization decision, then pass it back to the AuthorizationFilter.
Edit to add
Looking again,the base interface is AuthorizationManager<T> but the constructor for AuthorizationFilter expects to receive an AuthorizationManager<HttpServletRequest>. Your code might compile initially, but you'll probably get an exception when AuthorizationManager calls one of the methods with the wrong type for T object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With