To compose two authorization managers, some boilerplate is necessary. For example, to achieve a logical "or" between two authorization managers, they can be composed like so:

(authentication, object) -> {
    AuthorizationDecision decision = this.first.check(authentication, object);
    if (decision != null && decision.isGranted()) {
        return decision;
    }
    return this.second.check(authentication, object);
}

It would be nice to have an easy way to compose authorization managers in an "any" or "all" fashion, similar to the AffirmativeBased and UnanimousBased access decision managers.

One way to do this would be to introduce a static class AuthorizationManagers with convenience methods like so:

public static <T> AuthorizationManager<T> any(AuthorizationManager<T>... authorizationManagers);

public static <T> AuthorizationManager<T> all(AuthorizationManager<T>... authorizationManagers);

Then, the above code could be simplified to:

AuthorizationManagers.any(this.first, this.second);

Comment From: evgeniycheban

Hi, @jzheaux I can take this.

Comment From: gourav

Hi @jzheaux May I work on this ?

Comment From: jzheaux

@evgeniycheban, @gourav thanks both for your interest.

Since @evgeniycheban was first to post, I'll assign to him. @gourav please consider helping out with the review process once a PR is ready.

Comment From: KaVeKa

I believe there is a small difference in the implementation between AffirmativeBased and AuthorizationManagers.anyOf(). More precisely in handling AccessDecisionVoter.ABSTAIN vs a null instance of AuthorizationDecision.

Given 2 AuthorizationDecisions: null and new AuthorizationDecision(false) AffirmativeBased will deny access because it checks all votes, while the AuthorizationManagers.anyOf() will allow access because of the shortcut on decision == null.

It is documented clearly in the javadoc in AuthorizationManagers, but the migration docs make it seem like this is completely equivalent.

Just wanted to note this small discrepancy in the documentation :-)