Skip to content

AffirmativeBased vs. AuthorizationManagers.anyOf(...) documentation #13069

@kevinvankeer

Description

@kevinvankeer

I did not know whether to log this as a bug or an enhancement, but it feels more like a bug to me. Either in the migration documentation or in code. :-)

Describe the bug
Given 2 AuthorizationManagers/DecisionVoters:

  • AffirmativeBased way of working denies access when the first DecisionVoterabstains and the second denies.
  • AuthorizationManagers.anyOf(...) allows access when the first AuthorizationManagerabstains.

To Reproduce
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.

AffirmativeBased.java

public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException {
    int deny = 0;
    for (AccessDecisionVoter voter : getDecisionVoters()) {
	    int result = voter.vote(authentication, object, configAttributes);
	    switch (result) {
	    case AccessDecisionVoter.ACCESS_GRANTED:
		    return;
	    case AccessDecisionVoter.ACCESS_DENIED:
		    deny++;
		    break;
	    default:
		    break; // --> Continues the loop and checks all DecisionVoters.
	    }
    }
    if (deny > 0) {
	    throw new AccessDeniedException(
			    this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
    }
    // To get this far, every AccessDecisionVoter abstained
    checkAllowIfAllAbstainDecisions();
}

AuthorizationManagers.java

public static <T> AuthorizationManager<T> anyOf(AuthorizationManager<T>... managers) {
    return (authentication, object) -> {
	    List<AuthorizationDecision> decisions = new ArrayList<>();
	    for (AuthorizationManager<T> manager : managers) {
		    AuthorizationDecision decision = manager.check(authentication, object);
		    if (decision == null || decision.isGranted()) {
			    return decision; // --> Shortcuts the whole decision making process. Basically says ABSTAIN == GRANTED
		    }
		    decisions.add(decision);
	    }
	    return new CompositeAuthorizationDecision(false, decisions);
    };
}

Expected behavior
The behavior should be the same, or the migration docs should state that the implementations are not equivalent.

Metadata

Metadata

Assignees

Labels

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

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions