diff --git a/core/src/main/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManager.java index 9506f475fa5..8691b0333cb 100644 --- a/core/src/main/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManager.java +++ b/core/src/main/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManager.java @@ -99,7 +99,7 @@ public FactorAuthorizationDecision authorize(Supplier currentFactors) { Optional matchingAuthority = currentFactors.stream() - .filter((authority) -> authority.getAuthority().equals(requiredFactor.getAuthority())) + .filter((authority) -> Objects.equals(authority.getAuthority(), requiredFactor.getAuthority())) .findFirst(); if (!matchingAuthority.isPresent()) { return RequiredFactorError.createMissing(requiredFactor); diff --git a/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java b/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java index f9661578284..cc25cc5f9f9 100644 --- a/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java +++ b/core/src/main/java/org/springframework/security/authorization/AuthorityReactiveAuthorizationManager.java @@ -17,7 +17,10 @@ package org.springframework.security.authorization; import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; import org.springframework.security.core.Authentication; @@ -47,8 +50,8 @@ public Mono authorize(Mono authentication, // @formatter:off return authentication.filter(Authentication::isAuthenticated) .flatMapIterable(Authentication::getAuthorities) - .map(GrantedAuthority::getAuthority) - .any((grantedAuthority) -> this.authorities.stream().anyMatch((authority) -> authority.getAuthority().equals(grantedAuthority))) + .mapNotNull((Function) GrantedAuthority::getAuthority) + .any((grantedAuthority) -> this.authorities.stream().anyMatch((authority) -> Objects.equals(authority.getAuthority(), grantedAuthority))) .map((granted) -> ((AuthorizationResult) new AuthorityAuthorizationDecision(granted, this.authorities))) .defaultIfEmpty(new AuthorityAuthorizationDecision(false, this.authorities)); // @formatter:on diff --git a/core/src/main/java/org/springframework/security/core/GrantedAuthority.java b/core/src/main/java/org/springframework/security/core/GrantedAuthority.java index 143b254b854..cc2b379acda 100644 --- a/core/src/main/java/org/springframework/security/core/GrantedAuthority.java +++ b/core/src/main/java/org/springframework/security/core/GrantedAuthority.java @@ -18,6 +18,8 @@ import java.io.Serializable; +import org.jspecify.annotations.Nullable; + import org.springframework.security.authorization.AuthorizationManager; /** @@ -46,6 +48,6 @@ public interface GrantedAuthority extends Serializable { * granted authority cannot be expressed as a String with sufficient * precision). */ - String getAuthority(); + @Nullable String getAuthority(); } diff --git a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java index 69f85d0b668..218e760d922 100644 --- a/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java +++ b/core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java @@ -64,7 +64,10 @@ public void afterPropertiesSet() { public Set mapAuthorities(Collection authorities) { HashSet mapped = new HashSet<>(authorities.size()); for (GrantedAuthority authority : authorities) { - mapped.add(mapAuthority(authority.getAuthority())); + String authorityStr = authority.getAuthority(); + if (authorityStr != null) { + mapped.add(mapAuthority(authorityStr)); + } } if (this.defaultAuthority != null) { mapped.add(this.defaultAuthority); diff --git a/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java b/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java index c668a665d34..1b1e73badd0 100644 --- a/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java +++ b/test/src/main/java/org/springframework/security/test/web/servlet/response/SecurityMockMvcResultMatchers.java @@ -281,7 +281,8 @@ public AuthenticatedMatcher withRoles(String rolePrefix, String[] roles) { for (String role : roles) { withPrefix.add(new SimpleGrantedAuthority(rolePrefix + role)); } - this.ignoreAuthorities = (authority) -> !authority.getAuthority().startsWith(rolePrefix); + this.ignoreAuthorities = (authority) -> (authority.getAuthority() != null + && !authority.getAuthority().startsWith(rolePrefix)); return withAuthorities(withPrefix); } diff --git a/web/src/main/java/org/springframework/security/web/access/DelegatingMissingAuthorityAccessDeniedHandler.java b/web/src/main/java/org/springframework/security/web/access/DelegatingMissingAuthorityAccessDeniedHandler.java index a4f42b9c86a..5c110affc8c 100644 --- a/web/src/main/java/org/springframework/security/web/access/DelegatingMissingAuthorityAccessDeniedHandler.java +++ b/web/src/main/java/org/springframework/security/web/access/DelegatingMissingAuthorityAccessDeniedHandler.java @@ -162,7 +162,8 @@ private List authorityErrors(AccessDeniedExce if (authorizationResult instanceof AuthorityAuthorizationDecision authorityDecision) { // @formatter:off return authorityDecision.getAuthorities().stream() - .map((grantedAuthority) -> { + .filter((ga) -> ga.getAuthority() != null) + .map((grantedAuthority) -> { String authority = grantedAuthority.getAuthority(); if (authority.startsWith("FACTOR_")) { RequiredFactor required = RequiredFactor.withAuthority(authority).build();