Bläddra i källkod

Use Supplier<? extends @Nullable Authentication>

Previously Supplier<@Nullable Authentication> was used. This prevented
Supplier<Authentication> from being used. The code now uses
Supplier<? extends @Nullable Authentication> which allows for both
Supplier<@Nullable Authentication> and Supplier<Authentication>.

Closes gh-17814
Rob Winch 1 vecka sedan
förälder
incheckning
49f308adb0
32 ändrade filer med 70 tillägg och 43 borttagningar
  1. 3 1
      config/src/main/java/org/springframework/security/config/method/PointcutDelegatingAuthorizationManager.java
  2. 2 1
      config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java
  3. 2 3
      config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt
  4. 2 1
      config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java
  5. 3 1
      config/src/test/java/org/springframework/security/config/method/MethodSecurityBeanDefinitionParserTests.java
  6. 2 1
      config/src/test/java/org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests.java
  7. 1 1
      config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt
  8. 2 1
      core/src/main/java/org/springframework/security/access/expression/SecurityExpressionHandler.java
  9. 1 1
      core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java
  10. 2 2
      core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java
  11. 1 1
      core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java
  12. 1 1
      core/src/main/java/org/springframework/security/authorization/AuthenticatedAuthorizationManager.java
  13. 1 1
      core/src/main/java/org/springframework/security/authorization/AuthoritiesAuthorizationManager.java
  14. 1 1
      core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationManager.java
  15. 2 2
      core/src/main/java/org/springframework/security/authorization/AuthorizationManager.java
  16. 6 4
      core/src/main/java/org/springframework/security/authorization/AuthorizationManagers.java
  17. 2 1
      core/src/main/java/org/springframework/security/authorization/ObservationAuthorizationManager.java
  18. 1 1
      core/src/main/java/org/springframework/security/authorization/SingleResultAuthorizationManager.java
  19. 2 2
      core/src/main/java/org/springframework/security/authorization/method/Jsr250AuthorizationManager.java
  20. 2 1
      core/src/main/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManager.java
  21. 1 1
      core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java
  22. 1 1
      core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java
  23. 1 1
      core/src/main/java/org/springframework/security/authorization/method/SecuredAuthorizationManager.java
  24. 6 3
      messaging/src/main/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandler.java
  25. 3 1
      messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageAuthorizationContextSecurityExpressionHandler.java
  26. 1 1
      messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageSecurityExpressionRoot.java
  27. 3 1
      messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageMatcherDelegatingAuthorizationManager.java
  28. 3 1
      web/src/main/java/org/springframework/security/web/access/IpAddressAuthorizationManager.java
  29. 4 2
      web/src/main/java/org/springframework/security/web/access/expression/DefaultHttpSecurityExpressionHandler.java
  30. 4 1
      web/src/main/java/org/springframework/security/web/access/expression/WebExpressionAuthorizationManager.java
  31. 1 1
      web/src/main/java/org/springframework/security/web/access/expression/WebSecurityExpressionRoot.java
  32. 3 1
      web/src/main/java/org/springframework/security/web/access/intercept/RequestMatcherDelegatingAuthorizationManager.java

+ 3 - 1
config/src/main/java/org/springframework/security/config/method/PointcutDelegatingAuthorizationManager.java

@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.function.Supplier;
 
 import org.aopalliance.intercept.MethodInvocation;
+import org.jspecify.annotations.Nullable;
 
 import org.springframework.aop.Pointcut;
 import org.springframework.aop.support.AopUtils;
@@ -37,7 +38,8 @@ class PointcutDelegatingAuthorizationManager implements AuthorizationManager<Met
 	}
 
 	@Override
-	public AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation object) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
+			MethodInvocation object) {
 		for (Map.Entry<Pointcut, AuthorizationManager<MethodInvocation>> entry : this.managers.entrySet()) {
 			Class<?> targetClass = (object.getThis() != null) ? AopUtils.getTargetClass(object.getThis()) : null;
 			if (entry.getKey().getClassFilter().matches(targetClass)

+ 2 - 1
config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java

@@ -25,6 +25,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.function.Supplier;
 
+import org.jspecify.annotations.Nullable;
 import org.w3c.dom.Element;
 
 import org.springframework.beans.BeansException;
@@ -458,7 +459,7 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements
 		}
 
 		@Override
-		public AuthorizationResult authorize(Supplier<Authentication> authentication,
+		public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 				MessageAuthorizationContext<?> object) {
 			EvaluationContext context = this.expressionHandler.createEvaluationContext(authentication, object);
 			boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, context);

+ 2 - 3
config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt

@@ -29,7 +29,6 @@ import org.springframework.security.config.annotation.web.configurers.AuthorizeH
 import org.springframework.security.config.core.GrantedAuthorityDefaults
 import org.springframework.security.core.Authentication
 import org.springframework.security.web.access.IpAddressAuthorizationManager
-import org.springframework.security.web.access.intercept.AuthorizationFilter
 import org.springframework.security.web.access.intercept.RequestAuthorizationContext
 import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
 import org.springframework.security.web.util.matcher.AnyRequestMatcher
@@ -235,13 +234,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
      * Specify that URLs are allowed by anyone.
      */
     val permitAll: AuthorizationManager<RequestAuthorizationContext> =
-        AuthorizationManager { _: Supplier<Authentication?>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
+        AuthorizationManager { _: Supplier<out Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
 
     /**
      * Specify that URLs are not allowed by anyone.
      */
     val denyAll: AuthorizationManager<RequestAuthorizationContext> =
-        AuthorizationManager { _: Supplier<Authentication?>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
+        AuthorizationManager { _: Supplier<out Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
 
     /**
      * Specify that URLs are allowed by any authenticated user.

+ 2 - 1
config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java

@@ -25,6 +25,7 @@ import javax.security.auth.login.LoginContext;
 
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpSession;
+import org.jspecify.annotations.Nullable;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
@@ -310,7 +311,7 @@ public class NamespaceHttpTests {
 			}
 
 			@Override
-			public AuthorizationResult authorize(Supplier<Authentication> authentication,
+			public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 					RequestAuthorizationContext object) {
 				HttpServletRequest request = object.getRequest();
 				FilterInvocation invocation = new FilterInvocation(request.getContextPath(), request.getServletPath(),

+ 3 - 1
config/src/test/java/org/springframework/security/config/method/MethodSecurityBeanDefinitionParserTests.java

@@ -464,7 +464,9 @@ public class MethodSecurityBeanDefinitionParserTests {
 	static class MyAuthorizationManager implements AuthorizationManager<MethodInvocation> {
 
 		@Override
-		public AuthorizationResult authorize(Supplier<Authentication> authentication, MethodInvocation object) {
+		public AuthorizationResult authorize(
+				Supplier<? extends @org.jspecify.annotations.Nullable Authentication> authentication,
+				MethodInvocation object) {
 			return new AuthorizationDecision("bob".equals(authentication.get().getName()));
 		}
 

+ 2 - 1
config/src/test/java/org/springframework/security/config/websocket/WebSocketMessageBrokerConfigTests.java

@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.function.Supplier;
 
 import org.assertj.core.api.ThrowableAssert;
+import org.jspecify.annotations.Nullable;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
@@ -735,7 +736,7 @@ public class WebSocketMessageBrokerConfigTests {
 		}
 
 		@Override
-		public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
+		public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
 				Message<Object> message) {
 			return new StandardEvaluationContext(new MessageSecurityExpressionRoot(authentication, message) {
 				public boolean denyNile() {

+ 1 - 1
config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt

@@ -193,7 +193,7 @@ class AuthorizeHttpRequestsDslTests {
     open class MvcMatcherPathVariablesConfig {
         @Bean
         open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
-            val access = AuthorizationManager { _: Supplier<Authentication?>, context: RequestAuthorizationContext ->
+            val access = AuthorizationManager { _: Supplier<out Authentication>, context: RequestAuthorizationContext ->
                 AuthorizationDecision(context.variables["userName"] == "user")
             }
             http {

+ 2 - 1
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionHandler.java

@@ -57,7 +57,8 @@ public interface SecurityExpressionHandler<T> extends AopInfrastructureBean {
 	 * @return the {@link EvaluationContext} to use
 	 * @since 5.8
 	 */
-	default EvaluationContext createEvaluationContext(Supplier<@Nullable Authentication> authentication, T invocation) {
+	default EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
+			T invocation) {
 		return createEvaluationContext(authentication.get(), invocation);
 	}
 

+ 1 - 1
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java

@@ -89,7 +89,7 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
 	 * Cannot be null.
 	 * @since 5.8
 	 */
-	public SecurityExpressionRoot(Supplier<@Nullable Authentication> authentication) {
+	public SecurityExpressionRoot(Supplier<? extends @Nullable Authentication> authentication) {
 		this.authentication = SingletonSupplier.of(() -> {
 			Authentication value = authentication.get();
 			Assert.notNull(value, "Authentication object cannot be null");

+ 2 - 2
core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java

@@ -85,7 +85,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
 	}
 
 	@Override
-	public EvaluationContext createEvaluationContext(Supplier<@Nullable Authentication> authentication,
+	public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
 			MethodInvocation mi) {
 		MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
 		MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(root, mi,
@@ -104,7 +104,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
 	}
 
 	private MethodSecurityExpressionOperations createSecurityExpressionRoot(
-			Supplier<@Nullable Authentication> authentication, MethodInvocation invocation) {
+			Supplier<? extends @Nullable Authentication> authentication, MethodInvocation invocation) {
 		MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
 		root.setThis(invocation.getThis());
 		root.setPermissionEvaluator(getPermissionEvaluator());

+ 1 - 1
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java

@@ -42,7 +42,7 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot implements Met
 		super(a);
 	}
 
-	MethodSecurityExpressionRoot(Supplier<@Nullable Authentication> authentication) {
+	MethodSecurityExpressionRoot(Supplier<? extends @Nullable Authentication> authentication) {
 		super(authentication);
 	}
 

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/AuthenticatedAuthorizationManager.java

@@ -113,7 +113,7 @@ public final class AuthenticatedAuthorizationManager<T> implements Authorization
 	 * @return an {@link AuthorizationDecision}
 	 */
 	@Override
-	public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, T object) {
 		boolean granted = this.authorizationStrategy.isGranted(authentication.get());
 		return new AuthorizationDecision(granted);
 	}

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/AuthoritiesAuthorizationManager.java

@@ -57,7 +57,7 @@ public final class AuthoritiesAuthorizationManager implements AuthorizationManag
 	 * @return an {@link AuthorityAuthorizationDecision}
 	 */
 	@Override
-	public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 			Collection<String> authorities) {
 		boolean granted = isGranted(authentication.get(), authorities);
 		return new AuthorityAuthorizationDecision(granted, AuthorityUtils.createAuthorityList(authorities));

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationManager.java

@@ -139,7 +139,7 @@ public final class AuthorityAuthorizationManager<T> implements AuthorizationMana
 	 * {@inheritDoc}
 	 */
 	@Override
-	public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, T object) {
 		return this.delegate.authorize(authentication, this.authorities);
 	}
 

+ 2 - 2
core/src/main/java/org/springframework/security/authorization/AuthorizationManager.java

@@ -39,7 +39,7 @@ public interface AuthorizationManager<T extends @Nullable Object> {
 	 * @param object the {@link T} object to check
 	 * @throws AccessDeniedException if access is not granted
 	 */
-	default void verify(Supplier<@Nullable Authentication> authentication, T object) {
+	default void verify(Supplier<? extends @Nullable Authentication> authentication, T object) {
 		AuthorizationResult result = authorize(authentication, object);
 		if (result != null && !result.isGranted()) {
 			throw new AuthorizationDeniedException("Access Denied", result);
@@ -54,6 +54,6 @@ public interface AuthorizationManager<T extends @Nullable Object> {
 	 * @return an {@link AuthorizationResult}
 	 * @since 6.4
 	 */
-	@Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object);
+	@Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, T object);
 
 }

+ 6 - 4
core/src/main/java/org/springframework/security/authorization/AuthorizationManagers.java

@@ -60,7 +60,8 @@ public final class AuthorizationManagers {
 	@SafeVarargs
 	public static <T> AuthorizationManager<T> anyOf(AuthorizationDecision allAbstainDefaultDecision,
 			AuthorizationManager<T>... managers) {
-		return (AuthorizationManagerCheckAdapter<T>) (Supplier<@Nullable Authentication> authentication, T object) -> {
+		return (AuthorizationManagerCheckAdapter<T>) (Supplier<? extends @Nullable Authentication> authentication,
+				T object) -> {
 			List<AuthorizationResult> results = new ArrayList<>();
 			for (AuthorizationManager<T> manager : managers) {
 				AuthorizationResult result = manager.authorize(authentication, object);
@@ -106,7 +107,8 @@ public final class AuthorizationManagers {
 	@SafeVarargs
 	public static <T> AuthorizationManager<T> allOf(AuthorizationDecision allAbstainDefaultDecision,
 			AuthorizationManager<T>... managers) {
-		return (AuthorizationManagerCheckAdapter<T>) (Supplier<@Nullable Authentication> authentication, T object) -> {
+		return (AuthorizationManagerCheckAdapter<T>) (Supplier<? extends @Nullable Authentication> authentication,
+				T object) -> {
 			List<AuthorizationResult> results = new ArrayList<>();
 			for (AuthorizationManager<T> manager : managers) {
 				AuthorizationResult result = manager.authorize(authentication, object);
@@ -135,7 +137,7 @@ public final class AuthorizationManagers {
 	 * @since 6.3
 	 */
 	public static <T> AuthorizationManager<T> not(AuthorizationManager<T> manager) {
-		return (Supplier<@Nullable Authentication> authentication, T object) -> {
+		return (Supplier<? extends @Nullable Authentication> authentication, T object) -> {
 			AuthorizationResult result = manager.authorize(authentication, object);
 			if (result == null) {
 				return null;
@@ -184,7 +186,7 @@ public final class AuthorizationManagers {
 	private interface AuthorizationManagerCheckAdapter<T> extends AuthorizationManager<T> {
 
 		@Override
-		AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object);
+		AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, T object);
 
 	}
 

+ 2 - 1
core/src/main/java/org/springframework/security/authorization/ObservationAuthorizationManager.java

@@ -63,7 +63,8 @@ public final class ObservationAuthorizationManager<T>
 	}
 
 	@Override
-	public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, T object) {
+	public @Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
+			T object) {
 		AuthorizationObservationContext<T> context = new AuthorizationObservationContext<>(object);
 		Supplier<@Nullable Authentication> wrapped = () -> {
 			context.setAuthentication(authentication.get());

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/SingleResultAuthorizationManager.java

@@ -46,7 +46,7 @@ public final class SingleResultAuthorizationManager<C> implements AuthorizationM
 	}
 
 	@Override
-	public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, C object) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, C object) {
 		if (!(this.result instanceof AuthorizationDecision)) {
 			throw new IllegalArgumentException("result should be AuthorizationDecision");
 		}

+ 2 - 2
core/src/main/java/org/springframework/security/authorization/method/Jsr250AuthorizationManager.java

@@ -83,7 +83,7 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
 	 * {@inheritDoc}
 	 */
 	@Override
-	public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
+	public @Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 			MethodInvocation methodInvocation) {
 		AuthorizationManager<MethodInvocation> delegate = this.registry.getManager(methodInvocation);
 		return delegate.authorize(authentication, methodInvocation);
@@ -104,7 +104,7 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
 				return SingleResultAuthorizationManager.permitAll();
 			}
 			if (annotation instanceof RolesAllowed rolesAllowed) {
-				return (Supplier<@Nullable Authentication> a,
+				return (Supplier<? extends @Nullable Authentication> a,
 						MethodInvocation o) -> Jsr250AuthorizationManager.this.authoritiesAuthorizationManager
 							.authorize(a, getAllowedRolesWithPrefix(rolesAllowed));
 			}

+ 2 - 1
core/src/main/java/org/springframework/security/authorization/method/MethodExpressionAuthorizationManager.java

@@ -74,7 +74,8 @@ public final class MethodExpressionAuthorizationManager implements Authorization
 	 * expression
 	 */
 	@Override
-	public AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication, MethodInvocation context) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
+			MethodInvocation context) {
 		EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context);
 		boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx);
 		return new ExpressionAuthorizationDecision(granted, this.expression);

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java

@@ -86,7 +86,7 @@ public final class PostAuthorizeAuthorizationManager
 	 * {@link PostAuthorize} annotation is not present
 	 */
 	@Override
-	public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
+	public @Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 			MethodInvocationResult mi) {
 		ExpressionAttribute attribute = this.registry.getAttribute(mi.getMethodInvocation());
 		if (attribute == null) {

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java

@@ -78,7 +78,7 @@ public final class PreAuthorizeAuthorizationManager
 	 * {@link PreAuthorize} annotation is not present
 	 */
 	@Override
-	public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
+	public @Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 			MethodInvocation mi) {
 		ExpressionAttribute attribute = this.registry.getAttribute(mi);
 		if (attribute == null) {

+ 1 - 1
core/src/main/java/org/springframework/security/authorization/method/SecuredAuthorizationManager.java

@@ -68,7 +68,7 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
 	}
 
 	@Override
-	public @Nullable AuthorizationResult authorize(Supplier<@Nullable Authentication> authentication,
+	public @Nullable AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 			MethodInvocation mi) {
 		Set<String> authorities = getAuthorities(mi);
 		return authorities.isEmpty() ? null

+ 6 - 3
messaging/src/main/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandler.java

@@ -18,6 +18,8 @@ package org.springframework.security.messaging.access.expression;
 
 import java.util.function.Supplier;
 
+import org.jspecify.annotations.Nullable;
+
 import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.messaging.Message;
@@ -43,7 +45,8 @@ public class DefaultMessageSecurityExpressionHandler<T> extends AbstractSecurity
 	private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
 
 	@Override
-	public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, Message<T> message) {
+	public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
+			Message<T> message) {
 		MessageSecurityExpressionRoot root = createSecurityExpressionRoot(authentication, message);
 		StandardEvaluationContext ctx = new StandardEvaluationContext(root);
 		ctx.setBeanResolver(getBeanResolver());
@@ -56,8 +59,8 @@ public class DefaultMessageSecurityExpressionHandler<T> extends AbstractSecurity
 		return createSecurityExpressionRoot(() -> authentication, invocation);
 	}
 
-	private MessageSecurityExpressionRoot createSecurityExpressionRoot(Supplier<Authentication> authentication,
-			Message<T> invocation) {
+	private MessageSecurityExpressionRoot createSecurityExpressionRoot(
+			Supplier<? extends Authentication> authentication, Message<T> invocation) {
 		MessageSecurityExpressionRoot root = new MessageSecurityExpressionRoot(authentication, invocation);
 		root.setPermissionEvaluator(getPermissionEvaluator());
 		root.setTrustResolver(this.trustResolver);

+ 3 - 1
messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageAuthorizationContextSecurityExpressionHandler.java

@@ -19,6 +19,8 @@ package org.springframework.security.messaging.access.expression;
 import java.util.Map;
 import java.util.function.Supplier;
 
+import org.jspecify.annotations.Nullable;
+
 import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.ExpressionParser;
 import org.springframework.messaging.Message;
@@ -59,7 +61,7 @@ public final class MessageAuthorizationContextSecurityExpressionHandler
 	}
 
 	@Override
-	public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
+	public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
 			MessageAuthorizationContext<?> message) {
 		EvaluationContext context = this.delegate.createEvaluationContext(authentication, message.getMessage());
 		Map<String, String> variables = message.getVariables();

+ 1 - 1
messaging/src/main/java/org/springframework/security/messaging/access/expression/MessageSecurityExpressionRoot.java

@@ -44,7 +44,7 @@ public class MessageSecurityExpressionRoot extends SecurityExpressionRoot {
 	 * @param message the {@link Message} to use
 	 * @since 5.8
 	 */
-	public MessageSecurityExpressionRoot(Supplier<Authentication> authentication, Message<?> message) {
+	public MessageSecurityExpressionRoot(Supplier<? extends Authentication> authentication, Message<?> message) {
 		super(authentication);
 		this.message = message;
 	}

+ 3 - 1
messaging/src/main/java/org/springframework/security/messaging/access/intercept/MessageMatcherDelegatingAuthorizationManager.java

@@ -22,6 +22,7 @@ import java.util.function.Supplier;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.jspecify.annotations.Nullable;
 
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
@@ -54,7 +55,8 @@ public final class MessageMatcherDelegatingAuthorizationManager implements Autho
 	}
 
 	@Override
-	public AuthorizationResult authorize(Supplier<Authentication> authentication, Message<?> message) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
+			Message<?> message) {
 		if (this.logger.isTraceEnabled()) {
 			this.logger.trace(LogMessage.format("Authorizing message"));
 		}

+ 3 - 1
web/src/main/java/org/springframework/security/web/access/IpAddressAuthorizationManager.java

@@ -18,6 +18,8 @@ package org.springframework.security.web.access;
 
 import java.util.function.Supplier;
 
+import org.jspecify.annotations.Nullable;
+
 import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.AuthorizationManager;
 import org.springframework.security.authorization.AuthorizationResult;
@@ -53,7 +55,7 @@ public final class IpAddressAuthorizationManager implements AuthorizationManager
 	}
 
 	@Override
-	public AuthorizationResult authorize(Supplier<Authentication> authentication,
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
 			RequestAuthorizationContext requestAuthorizationContext) {
 		return new AuthorizationDecision(
 				this.ipAddressMatcher.matcher(requestAuthorizationContext.getRequest()).isMatch());

+ 4 - 2
web/src/main/java/org/springframework/security/web/access/expression/DefaultHttpSecurityExpressionHandler.java

@@ -18,6 +18,8 @@ package org.springframework.security.web.access.expression;
 
 import java.util.function.Supplier;
 
+import org.jspecify.annotations.Nullable;
+
 import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
@@ -44,7 +46,7 @@ public class DefaultHttpSecurityExpressionHandler extends AbstractSecurityExpres
 	private String defaultRolePrefix = "ROLE_";
 
 	@Override
-	public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
+	public EvaluationContext createEvaluationContext(Supplier<? extends @Nullable Authentication> authentication,
 			RequestAuthorizationContext context) {
 		WebSecurityExpressionRoot root = createSecurityExpressionRoot(authentication, context);
 		StandardEvaluationContext ctx = new StandardEvaluationContext(root);
@@ -59,7 +61,7 @@ public class DefaultHttpSecurityExpressionHandler extends AbstractSecurityExpres
 		return createSecurityExpressionRoot(() -> authentication, context);
 	}
 
-	private WebSecurityExpressionRoot createSecurityExpressionRoot(Supplier<Authentication> authentication,
+	private WebSecurityExpressionRoot createSecurityExpressionRoot(Supplier<? extends Authentication> authentication,
 			RequestAuthorizationContext context) {
 		WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, context.getRequest());
 		root.setRoleHierarchy(getRoleHierarchy());

+ 4 - 1
web/src/main/java/org/springframework/security/web/access/expression/WebExpressionAuthorizationManager.java

@@ -18,6 +18,8 @@ package org.springframework.security.web.access.expression;
 
 import java.util.function.Supplier;
 
+import org.jspecify.annotations.Nullable;
+
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
@@ -83,7 +85,8 @@ public final class WebExpressionAuthorizationManager implements AuthorizationMan
 	 * expression
 	 */
 	@Override
-	public AuthorizationResult authorize(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
+			RequestAuthorizationContext context) {
 		EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context);
 		boolean granted = ExpressionUtils.evaluateAsBoolean(this.expression, ctx);
 		return new ExpressionAuthorizationDecision(granted, this.expression);

+ 1 - 1
web/src/main/java/org/springframework/security/web/access/expression/WebSecurityExpressionRoot.java

@@ -48,7 +48,7 @@ public class WebSecurityExpressionRoot extends SecurityExpressionRoot {
 	 * @param request the {@link HttpServletRequest} to use
 	 * @since 5.8
 	 */
-	public WebSecurityExpressionRoot(Supplier<Authentication> authentication, HttpServletRequest request) {
+	public WebSecurityExpressionRoot(Supplier<? extends Authentication> authentication, HttpServletRequest request) {
 		super(authentication);
 		this.request = request;
 	}

+ 3 - 1
web/src/main/java/org/springframework/security/web/access/intercept/RequestMatcherDelegatingAuthorizationManager.java

@@ -24,6 +24,7 @@ import java.util.function.Supplier;
 import jakarta.servlet.http.HttpServletRequest;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.jspecify.annotations.Nullable;
 
 import org.springframework.core.log.LogMessage;
 import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
@@ -63,7 +64,8 @@ public final class RequestMatcherDelegatingAuthorizationManager implements Autho
 	}
 
 	@Override
-	public AuthorizationResult authorize(Supplier<Authentication> authentication, HttpServletRequest request) {
+	public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication,
+			HttpServletRequest request) {
 		if (this.logger.isTraceEnabled()) {
 			this.logger.trace(LogMessage.format("Authorizing %s", requestLine(request)));
 		}