spring-projects/spring-security · error · AccessDeniedException

Access is denied

Error message

Access is denied

What it means

AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions() throws AccessDeniedException when every AccessDecisionVoter abstained and the 'allowIfAllAbstainDecisions' flag is false. Default security posture: abstention means deny.

Source

Thrown at access/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java:71

	protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

	private boolean allowIfAllAbstainDecisions = false;

	protected AbstractAccessDecisionManager(List<AccessDecisionVoter<?>> decisionVoters) {
		Assert.notEmpty(decisionVoters, "A list of AccessDecisionVoters is required");
		this.decisionVoters = decisionVoters;
	}

	@Override
	public void afterPropertiesSet() {
		Assert.notEmpty(this.decisionVoters, "A list of AccessDecisionVoters is required");
		Assert.notNull(this.messages, "A message source must be set");
	}

	protected final void checkAllowIfAllAbstainDecisions() {
		if (!this.isAllowIfAllAbstainDecisions()) {
			throw new AccessDeniedException(
					this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
		}
	}

	public List<AccessDecisionVoter<?>> getDecisionVoters() {
		return this.decisionVoters;
	}

	public boolean isAllowIfAllAbstainDecisions() {
		return this.allowIfAllAbstainDecisions;
	}

	public void setAllowIfAllAbstainDecisions(boolean allowIfAllAbstainDecisions) {
		this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions;
	}

	@Override
	public void setMessageSource(MessageSource messageSource) {

View on GitHub (pinned to 96852e8860)

Solutions

  1. Set allowIfAllAbstainDecisions(true) on the decision manager if abstain should grant
  2. Fix voter configuration so the relevant attributes are actually voted on (check RolePrefix, supported attribute types)
  3. Ensure the secured invocation carries config attributes your voters understand
  4. Add or register the appropriate voters (RoleVoter, AuthenticatedVoter, etc.)

Example fix

// before
AffirmativeBased am = new AffirmativeBased(voters);
// abstentions denied

// after
AffirmativeBased am = new AffirmativeBased(voters);
am.setAllowIfAllAbstainDecisions(true);
Defensive patterns

Strategy: validation

Validate before calling

if (voters.stream().noneMatch(v -> v.supports(configAttribute))) {
    throw new IllegalStateException("No voter supports attribute " + configAttribute);
}

Type guard

null

Try / catch

try {
    decisionManager.decide(auth, object, attrs);
} catch (AccessDeniedException e) {
    log.debug("All voters abstained and abstain-grant is disabled");
    throw e;
}

Prevention

When it happens

Trigger: decide() on AffirmativeBased/ConsensusBased/UnanimousBased completes with zero grant/deny votes and allowIfAllAbstainDecisions (default false) denies; e.g. no voter has a config attribute matching the secured method's attributes.

Common situations: Method security annotations whose attributes no voter recognizes (e.g. ROLE_ prefix mismatch, missing RoleVoter), empty voter list, or custom voter abstaining because ConfigAttribute is unsupported.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/c65d948cc16ddda8. Report an issue: GitHub.