Spring Security provides expressive ways to declare authorization. For example HttpSecurity
provides:
http
.authorizeHttpRequests((r) -> r
.requestMatchers("/admin/**").hasRole("ADMIN")
)
Right now this always maps to AuthorityAuthorizationManager.hasRole(String)
. However, there may be times users want it to map to a custom AuthorizationManager
. For example, they might want to map it to something like OPA, OpenFG, or some other external service.
These customizations can currently be done using something like, but it looses some of its expressiveness and makes it more difficult to swap out the implementation:
http
.authorizeHttpRequests((r) -> r
.requestMatchers("/admin/**").access(new CustomAuthorizationManager())
)
For this ticket we should:
1) We should create an API that abstracts how the expressions are created and delegates to the existing APIs. For example:
public interface AuthorizationManagerFactory<T> {
AuthorizationManager<T> permitAll();
AuthorizationManager<T> denyAll();
AuthorizationManager<T> hasRole(String role);
AuthorizationManager<T> hasAnyRole(String... roles);
AuthorizationManager<T> hasAuthority(String authority);
AuthorizationManager<T> hasAnyAuthority(String... authorities);
....
}
2) Create a default implementation that delegates to the existing static methods that are used now.
3) Update Then the HttpSecurity
DSL would use the default implementation that delegates to the existing static methods. If an AuthorizationManagerFactory
Bean is published, it would be used by the DSL. This should be generic aware to ensure that it doesn't pick a factory that creates the wrong AuthorizationManager
types.
4) Similar to HttpSecurity
, update Method Security use a default AuthorizationManagerFactory
but if a Bean is published, then use it. This should be generic aware to ensure that it doesn't pick a factory that creates the wrong AuthorizationManager
types.
cc @sjohnr
Comment From: sjohnr
Hey @rwinch, I'd like to tackle this one if I may.
Comment From: rwinch
Thanks @sjohnr! The issue is all yours!