diff --git a/cas/spring-security-cas.gradle b/cas/spring-security-cas.gradle
index fd4a614fa5..a475013057 100644
--- a/cas/spring-security-cas.gradle
+++ b/cas/spring-security-cas.gradle
@@ -1,3 +1,7 @@
+plugins {
+ id 'security-nullability'
+}
+
apply plugin: 'io.spring.convention.spring-module'
dependencies {
diff --git a/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java b/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java
index caf03dd62a..450142e8ef 100644
--- a/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java
+++ b/cas/src/main/java/org/springframework/security/cas/ServiceProperties.java
@@ -16,6 +16,8 @@
package org.springframework.security.cas;
+import org.jspecify.annotations.Nullable;
+
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -34,7 +36,7 @@ public class ServiceProperties implements InitializingBean {
public static final String DEFAULT_CAS_SERVICE_PARAMETER = "service";
- private String service;
+ private @Nullable String service;
private boolean authenticateAllArtifacts;
@@ -62,7 +64,7 @@ public class ServiceProperties implements InitializingBean {
*
* @return the URL of the service the user is authenticating to
*/
- public final String getService() {
+ public final @Nullable String getService() {
return this.service;
}
diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java
index 0779a509a6..9955b11e71 100644
--- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java
+++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java
@@ -21,6 +21,8 @@ import org.apache.commons.logging.LogFactory;
import org.apereo.cas.client.validation.Assertion;
import org.apereo.cas.client.validation.TicketValidationException;
import org.apereo.cas.client.validation.TicketValidator;
+import org.jspecify.annotations.NullUnmarked;
+import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
@@ -62,6 +64,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia
private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
+ @SuppressWarnings("NullAway.Init")
private AuthenticationUserDetailsService
CasAuthenticationToken to the cache.
diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java b/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java
index bebdce4140..4cfab548f9 100644
--- a/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java
+++ b/cas/src/main/java/org/springframework/security/cas/authentication/package-info.java
@@ -18,4 +18,7 @@
* An {@code AuthenticationProvider} that can process CAS service tickets and proxy
* tickets.
*/
+@NullMarked
package org.springframework.security.cas.authentication;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cas/src/main/java/org/springframework/security/cas/jackson2/package-info.java b/cas/src/main/java/org/springframework/security/cas/jackson2/package-info.java
new file mode 100644
index 0000000000..dae1c1502d
--- /dev/null
+++ b/cas/src/main/java/org/springframework/security/cas/jackson2/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2004-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Jackson support for CAS.
+ */
+@NullMarked
+package org.springframework.security.cas.jackson2;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cas/src/main/java/org/springframework/security/cas/package-info.java b/cas/src/main/java/org/springframework/security/cas/package-info.java
index a3ce420968..90592aa897 100644
--- a/cas/src/main/java/org/springframework/security/cas/package-info.java
+++ b/cas/src/main/java/org/springframework/security/cas/package-info.java
@@ -18,4 +18,7 @@
* Spring Security support for Apereo's Central Authentication Service
* (CAS).
*/
+@NullMarked
package org.springframework.security.cas;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cas/src/main/java/org/springframework/security/cas/userdetails/package-info.java b/cas/src/main/java/org/springframework/security/cas/userdetails/package-info.java
new file mode 100644
index 0000000000..24681a528a
--- /dev/null
+++ b/cas/src/main/java/org/springframework/security/cas/userdetails/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2004-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * {@link org.springframework.security.core.userdetails.UserDetails} abstractions for CAS.
+ */
+@NullMarked
+package org.springframework.security.cas.userdetails;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java
index 539ab57ccd..59aaff4474 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationEntryPoint.java
@@ -22,6 +22,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apereo.cas.client.util.CommonUtils;
import org.apereo.cas.client.util.WebUtils;
+import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.cas.ServiceProperties;
@@ -47,9 +48,10 @@ import org.springframework.util.Assert;
*/
public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
+ @SuppressWarnings("NullAway.Init")
private ServiceProperties serviceProperties;
- private String loginUrl;
+ private @Nullable String loginUrl;
/**
* Determines whether the Service URL should include the session id for the specific
@@ -117,7 +119,7 @@ public class CasAuthenticationEntryPoint implements AuthenticationEntryPoint, In
* https://www.mycompany.com/cas/login.
* @return the enterprise-wide CAS login URL
*/
- public final String getLoginUrl() {
+ public final @Nullable String getLoginUrl() {
return this.loginUrl;
}
diff --git a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java
index ddc01f51ca..06623db874 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java
@@ -26,6 +26,7 @@ import jakarta.servlet.http.HttpSession;
import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
import org.apereo.cas.client.util.WebUtils;
import org.apereo.cas.client.validation.TicketValidator;
+import org.jspecify.annotations.Nullable;
import org.springframework.core.log.LogMessage;
import org.springframework.security.authentication.AuthenticationDetailsSource;
@@ -190,12 +191,12 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
/**
* The last portion of the receptor url, i.e. /proxy/receptor
*/
- private RequestMatcher proxyReceptorMatcher;
+ private @Nullable RequestMatcher proxyReceptorMatcher;
/**
* The backing storage to store ProxyGrantingTicket requests.
*/
- private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
+ private @Nullable ProxyGrantingTicketStorage proxyGrantingTicketStorage;
private String artifactParameter = ServiceProperties.DEFAULT_CAS_ARTIFACT_PARAMETER;
@@ -244,7 +245,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
}
@Override
- public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
+ public @Nullable Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException {
// if the request is a proxy request process it and return null to indicate the
// request has been processed
@@ -422,6 +423,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
* @param request
* @return
*/
+ @SuppressWarnings("NullAway") // Dataflow analysis limitation
private boolean proxyReceptorRequest(HttpServletRequest request) {
final boolean result = proxyReceptorConfigured() && this.proxyReceptorMatcher.matches(request);
this.logger.debug(LogMessage.format("proxyReceptorRequest = %s", result));
diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java
index bb5fe0d793..cbfe9825cc 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/DefaultServiceAuthenticationDetails.java
@@ -21,6 +21,7 @@ import java.net.URL;
import java.util.regex.Pattern;
import jakarta.servlet.http.HttpServletRequest;
+import org.jspecify.annotations.Nullable;
import org.springframework.security.cas.authentication.ServiceAuthenticationDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
@@ -49,8 +50,8 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
* string from containing the artifact name and value. This can be created using
* {@link #createArtifactPattern(String)}.
*/
- DefaultServiceAuthenticationDetails(String casService, HttpServletRequest request, Pattern artifactPattern)
- throws MalformedURLException {
+ DefaultServiceAuthenticationDetails(@Nullable String casService, HttpServletRequest request,
+ Pattern artifactPattern) throws MalformedURLException {
super(request);
URL casServiceUrl = new URL(casService);
int port = getServicePort(casServiceUrl);
@@ -104,7 +105,7 @@ final class DefaultServiceAuthenticationDetails extends WebAuthenticationDetails
* @return the query String minus the artifactParameterName and the corresponding
* value.
*/
- private String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
+ private @Nullable String getQueryString(final HttpServletRequest request, final Pattern artifactPattern) {
final String query = request.getQueryString();
if (query == null) {
return null;
diff --git a/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java b/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java
index 5b415a1424..ae1670e08b 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/authentication/package-info.java
@@ -18,4 +18,7 @@
* Authentication processing mechanisms which respond to the submission of authentication
* credentials using CAS.
*/
+@NullMarked
package org.springframework.security.cas.web.authentication;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/cas/src/main/java/org/springframework/security/cas/web/package-info.java b/cas/src/main/java/org/springframework/security/cas/web/package-info.java
index df1f9edff2..b89ed4d96b 100644
--- a/cas/src/main/java/org/springframework/security/cas/web/package-info.java
+++ b/cas/src/main/java/org/springframework/security/cas/web/package-info.java
@@ -17,4 +17,7 @@
/**
* Authenticates standard web browser users via CAS.
*/
+@NullMarked
package org.springframework.security.cas.web;
+
+import org.jspecify.annotations.NullMarked;
diff --git a/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java b/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java
index bc759f5f7a..436b9a5682 100644
--- a/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java
+++ b/core/src/main/java/org/springframework/security/authentication/BadCredentialsException.java
@@ -18,6 +18,8 @@ package org.springframework.security.authentication;
import java.io.Serial;
+import org.jspecify.annotations.Nullable;
+
import org.springframework.security.core.AuthenticationException;
/**
@@ -35,7 +37,7 @@ public class BadCredentialsException extends AuthenticationException {
* Constructs a BadCredentialsException with the specified message.
* @param msg the detail message
*/
- public BadCredentialsException(String msg) {
+ public BadCredentialsException(@Nullable String msg) {
super(msg);
}
@@ -45,7 +47,7 @@ public class BadCredentialsException extends AuthenticationException {
* @param msg the detail message
* @param cause root cause
*/
- public BadCredentialsException(String msg, Throwable cause) {
+ public BadCredentialsException(@Nullable String msg, Throwable cause) {
super(msg, cause);
}
diff --git a/core/src/main/java/org/springframework/security/core/AuthenticationException.java b/core/src/main/java/org/springframework/security/core/AuthenticationException.java
index 37fea816f1..e6e2d0662d 100644
--- a/core/src/main/java/org/springframework/security/core/AuthenticationException.java
+++ b/core/src/main/java/org/springframework/security/core/AuthenticationException.java
@@ -50,7 +50,7 @@ public abstract class AuthenticationException extends RuntimeException {
* root cause.
* @param msg the detail message
*/
- public AuthenticationException(String msg) {
+ public AuthenticationException(@Nullable String msg) {
super(msg);
}