spring-projects/spring-security · warning
Denying user permission ' ' on object with Id
Error message
Denying user %s permission '%s' on object with Id %s
What it means
The second DenyAllPermissionEvaluator overload handles hasPermission(authentication, targetId, targetType, permission) and, like the object-based variant, always logs a denial and returns false. It guarantees fail-closed behavior for id/targetType-based permission checks when no real evaluator is configured.
Solutions
- Register a custom PermissionEvaluator implementing hasPermission(Serializable targetId, String targetType, Object permission)
- Wire it into DefaultMethodSecurityExpressionHandler so it replaces the deny-all default
- Or rewrite expressions to not use hasPermission if a simpler authority check suffices
Example fix
// before: default evaluator denies
@PreAuthorize("hasPermission(#id, 'Document', 'READ')")
// after
expressionHandler.setPermissionEvaluator(new IdBasedPermissionEvaluator()); Defensive patterns
Strategy: validation
Validate before calling
// Same guard for the id/targetType overload
if (expressionHandler.getPermissionEvaluator() instanceof DenyAllPermissionEvaluator) {
throw new IllegalStateException("hasPermission(id,type,perm) will always deny; register an evaluator");
} Type guard
boolean supportsIdChecks(PermissionEvaluator pe) {
return !(pe instanceof DenyAllPermissionEvaluator);
} Prevention
- Implement both hasPermission overloads in custom evaluators
- Test id+targetType permission expressions explicitly
- Document which expression style your evaluator supports to avoid silent deny-all
When it happens
Trigger: A SpEL expression such as hasPermission(#id, 'com.example.Document', 'READ') is evaluated while DenyAllPermissionEvaluator is the active evaluator.
Common situations: Using id+type style hasPermission expressions without a custom PermissionEvaluator; accidentally relying on Spring Security's default deny-all evaluator in production.
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/040a492dbde6dc36.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/springframework/security/access/expression/DenyAllPermissionEvaluator.java:58
/**
* Always denies permission.
* @return false always
*/
@Override
public boolean hasPermission(Authentication authentication, @Nullable Object target, Object permission) {
this.logger.warn(LogMessage.format("Denying user %s permission '%s' on object %s", authentication.getName(),
permission, target));
return false;
}
/**
* Always denies permission.
* @return false always
*/
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
Object permission) {
this.logger.warn(LogMessage.format("Denying user %s permission '%s' on object with Id %s",
authentication.getName(), permission, targetId));
return false;
}
}
View on GitHub (pinned to 96852e8860)