Skip to content

Commit e771ec0

Browse files
committed
Add @nullable Annotations to saml2-service-provider
Issue gh-17823 Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
1 parent f3656b4 commit e771ec0

97 files changed

Lines changed: 971 additions & 398 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2Error.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.io.Serializable;
2020

21+
import org.jspecify.annotations.Nullable;
22+
2123
import org.springframework.util.Assert;
2224

2325
/**
@@ -37,14 +39,14 @@ public class Saml2Error implements Serializable {
3739

3840
private final String errorCode;
3941

40-
private final String description;
42+
private final @Nullable String description;
4143

4244
/**
4345
* Constructs a {@code Saml2Error} using the provided parameters.
4446
* @param errorCode the error code
4547
* @param description the error description
4648
*/
47-
public Saml2Error(String errorCode, String description) {
49+
public Saml2Error(String errorCode, @Nullable String description) {
4850
Assert.hasText(errorCode, "errorCode cannot be empty");
4951
this.errorCode = errorCode;
5052
this.description = description;
@@ -56,7 +58,7 @@ public Saml2Error(String errorCode, String description) {
5658
* @return the resulting {@link Saml2Error}
5759
* @since 7.0
5860
*/
59-
public static Saml2Error invalidResponse(String description) {
61+
public static Saml2Error invalidResponse(@Nullable String description) {
6062
return new Saml2Error(Saml2ErrorCodes.INVALID_RESPONSE, description);
6163
}
6264

@@ -66,7 +68,7 @@ public static Saml2Error invalidResponse(String description) {
6668
* @return the resulting {@link Saml2Error}
6769
* @since 7.0
6870
*/
69-
public static Saml2Error internalValidationError(String description) {
71+
public static Saml2Error internalValidationError(@Nullable String description) {
7072
return new Saml2Error(Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR, description);
7173
}
7274

@@ -76,7 +78,7 @@ public static Saml2Error internalValidationError(String description) {
7678
* @return the resulting {@link Saml2Error}
7779
* @since 7.0
7880
*/
79-
public static Saml2Error malformedResponseData(String description) {
81+
public static Saml2Error malformedResponseData(@Nullable String description) {
8082
return new Saml2Error(Saml2ErrorCodes.MALFORMED_RESPONSE_DATA, description);
8183
}
8284

@@ -86,7 +88,7 @@ public static Saml2Error malformedResponseData(String description) {
8688
* @return the resulting {@link Saml2Error}
8789
* @since 7.0
8890
*/
89-
public static Saml2Error decryptionError(String description) {
91+
public static Saml2Error decryptionError(@Nullable String description) {
9092
return new Saml2Error(Saml2ErrorCodes.DECRYPTION_ERROR, description);
9193
}
9294

@@ -96,7 +98,7 @@ public static Saml2Error decryptionError(String description) {
9698
* @return the resulting {@link Saml2Error}
9799
* @since 7.0
98100
*/
99-
public static Saml2Error relyingPartyRegistrationNotFound(String description) {
101+
public static Saml2Error relyingPartyRegistrationNotFound(@Nullable String description) {
100102
return new Saml2Error(Saml2ErrorCodes.RELYING_PARTY_REGISTRATION_NOT_FOUND, description);
101103
}
102104

@@ -106,7 +108,7 @@ public static Saml2Error relyingPartyRegistrationNotFound(String description) {
106108
* @return the resulting {@link Saml2Error}
107109
* @since 7.0
108110
*/
109-
public static Saml2Error subjectNotFound(String description) {
111+
public static Saml2Error subjectNotFound(@Nullable String description) {
110112
return new Saml2Error(Saml2ErrorCodes.SUBJECT_NOT_FOUND, description);
111113
}
112114

@@ -122,7 +124,7 @@ public final String getErrorCode() {
122124
* Returns the error description.
123125
* @return the error description
124126
*/
125-
public final String getDescription() {
127+
public final @Nullable String getDescription() {
126128
return this.description;
127129
}
128130

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/core/Saml2X509Credential.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.Objects;
2525
import java.util.Set;
2626

27+
import org.jspecify.annotations.Nullable;
28+
2729
import org.springframework.util.Assert;
2830

2931
/**
@@ -40,7 +42,7 @@ public final class Saml2X509Credential implements Serializable {
4042

4143
private static final long serialVersionUID = -1015853414272603517L;
4244

43-
private final PrivateKey privateKey;
45+
private final @Nullable PrivateKey privateKey;
4446

4547
private final X509Certificate certificate;
4648

@@ -77,7 +79,8 @@ public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, S
7779
* @param certificate the credential's public certificate
7880
* @param types the credential's intended usages
7981
*/
80-
public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Set<Saml2X509CredentialType> types) {
82+
public Saml2X509Credential(@Nullable PrivateKey privateKey, X509Certificate certificate,
83+
Set<Saml2X509CredentialType> types) {
8184
Assert.notNull(certificate, "certificate cannot be null");
8285
Assert.notNull(types, "credentialTypes cannot be null");
8386
this.privateKey = privateKey;
@@ -123,7 +126,7 @@ public static Saml2X509Credential signing(PrivateKey privateKey, X509Certificate
123126
return new Saml2X509Credential(privateKey, certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING);
124127
}
125128

126-
private Saml2X509Credential(PrivateKey privateKey, boolean keyRequired, X509Certificate certificate,
129+
private Saml2X509Credential(@Nullable PrivateKey privateKey, boolean keyRequired, X509Certificate certificate,
127130
Saml2X509CredentialType... types) {
128131
Assert.notNull(certificate, "certificate cannot be null");
129132
Assert.notEmpty(types, "credentials types cannot be empty");
@@ -140,7 +143,7 @@ private Saml2X509Credential(PrivateKey privateKey, boolean keyRequired, X509Cert
140143
* @return the private key, may be null
141144
* @see #Saml2X509Credential(PrivateKey, X509Certificate, Saml2X509CredentialType...)
142145
*/
143-
public PrivateKey getPrivateKey() {
146+
public @Nullable PrivateKey getPrivateKey() {
144147
return this.privateKey;
145148
}
146149

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Core SAML2 types and utilities.
19+
*/
20+
@NullMarked
21+
package org.springframework.security.saml2.core;
22+
23+
import org.jspecify.annotations.NullMarked;

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/internal/OpenSamlOperations.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import javax.xml.namespace.QName;
2727

28+
import org.jspecify.annotations.Nullable;
2829
import org.opensaml.core.xml.XMLObject;
2930
import org.opensaml.saml.saml2.core.Issuer;
3031
import org.opensaml.saml.saml2.core.RequestAbstractType;
@@ -35,6 +36,7 @@
3536
import org.springframework.security.saml2.core.Saml2Error;
3637
import org.springframework.security.saml2.core.Saml2ParameterNames;
3738
import org.springframework.security.saml2.core.Saml2X509Credential;
39+
import org.springframework.util.Assert;
3840
import org.springframework.web.util.UriComponentsBuilder;
3941

4042
interface OpenSamlOperations {
@@ -89,14 +91,17 @@ final class RedirectParameters {
8991

9092
private final String algorithm;
9193

92-
private final byte[] signature;
94+
private final byte @Nullable [] signature;
9395

9496
private final byte[] content;
9597

9698
RedirectParameters(Map<String, String> parameters, String parametersQuery, RequestAbstractType request) {
99+
Assert.notNull(request.getID(), "SAML request's ID cannot be null");
100+
Assert.notNull(request.getIssuer(), "SAML request's Issuer cannot be null");
97101
this.id = request.getID();
98102
this.issuer = request.getIssuer();
99-
this.algorithm = parameters.get(Saml2ParameterNames.SIG_ALG);
103+
this.algorithm = Objects.requireNonNull(parameters.get(Saml2ParameterNames.SIG_ALG),
104+
"sigAlg parameter cannot be null");
100105
if (parameters.get(Saml2ParameterNames.SIGNATURE) != null) {
101106
this.signature = Saml2Utils.samlDecode(parameters.get(Saml2ParameterNames.SIGNATURE));
102107
}
@@ -113,9 +118,12 @@ final class RedirectParameters {
113118
}
114119

115120
RedirectParameters(Map<String, String> parameters, String parametersQuery, StatusResponseType response) {
121+
Assert.notNull(response.getID(), "SAML response's ID cannot be null");
122+
Assert.notNull(response.getIssuer(), "SAML response's Issuer cannot be null");
116123
this.id = response.getID();
117124
this.issuer = response.getIssuer();
118-
this.algorithm = parameters.get(Saml2ParameterNames.SIG_ALG);
125+
this.algorithm = Objects.requireNonNull(parameters.get(Saml2ParameterNames.SIG_ALG),
126+
"sigAlg parameter cannot be null");
119127
if (parameters.get(Saml2ParameterNames.SIGNATURE) != null) {
120128
this.signature = Saml2Utils.samlDecode(parameters.get(Saml2ParameterNames.SIGNATURE));
121129
}
@@ -131,7 +139,8 @@ final class RedirectParameters {
131139
this.content = getContent(Saml2ParameterNames.SAML_RESPONSE, relayState, queryParams);
132140
}
133141

134-
static byte[] getContent(String samlObject, String relayState, final Map<String, String> queryParams) {
142+
static byte[] getContent(String samlObject, @Nullable String relayState,
143+
final Map<String, String> queryParams) {
135144
if (Objects.nonNull(relayState)) {
136145
return String
137146
.format("%s=%s&%s=%s&%s=%s", samlObject, queryParams.get(samlObject),
@@ -163,7 +172,7 @@ String getAlgorithm() {
163172
return this.algorithm;
164173
}
165174

166-
byte[] getSignature() {
175+
byte @Nullable [] getSignature() {
167176
return this.signature;
168177
}
169178

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Internal utilities for SAML2 support (not for public use).
19+
*/
20+
@NullMarked
21+
package org.springframework.security.saml2.internal;
22+
23+
import org.jspecify.annotations.NullMarked;

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson/DefaultSaml2AuthenticatedPrincipalMixin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2323
import com.fasterxml.jackson.annotation.JsonProperty;
2424
import com.fasterxml.jackson.annotation.JsonTypeInfo;
25+
import org.jspecify.annotations.NullUnmarked;
2526

2627
import org.springframework.security.jackson.SecurityJacksonModules;
2728
import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
@@ -38,6 +39,7 @@
3839
*/
3940
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
4041
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
42+
@NullUnmarked
4143
class DefaultSaml2AuthenticatedPrincipalMixin {
4244

4345
@JsonProperty("registrationId")

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson/Saml2AssertionAuthenticationMixin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.fasterxml.jackson.annotation.JsonCreator;
2323
import com.fasterxml.jackson.annotation.JsonProperty;
2424
import com.fasterxml.jackson.annotation.JsonTypeInfo;
25+
import org.jspecify.annotations.NullUnmarked;
2526

2627
import org.springframework.security.core.GrantedAuthority;
2728
import org.springframework.security.jackson.SecurityJacksonModules;
@@ -41,6 +42,7 @@
4142
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
4243
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
4344
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
45+
@NullUnmarked
4446
class Saml2AssertionAuthenticationMixin {
4547

4648
@JsonCreator

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson/Saml2AuthenticationExceptionMixin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2222
import com.fasterxml.jackson.annotation.JsonProperty;
2323
import com.fasterxml.jackson.annotation.JsonTypeInfo;
24+
import org.jspecify.annotations.NullUnmarked;
2425

2526
import org.springframework.security.saml2.core.Saml2Error;
2627
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
@@ -38,6 +39,7 @@
3839
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE,
3940
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
4041
@JsonIgnoreProperties({ "cause", "stackTrace", "suppressedExceptions" })
42+
@NullUnmarked
4143
abstract class Saml2AuthenticationExceptionMixin {
4244

4345
@JsonProperty("error")

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson/Saml2AuthenticationMixin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2424
import com.fasterxml.jackson.annotation.JsonProperty;
2525
import com.fasterxml.jackson.annotation.JsonTypeInfo;
26+
import org.jspecify.annotations.NullUnmarked;
2627

2728
import org.springframework.security.core.AuthenticatedPrincipal;
2829
import org.springframework.security.core.GrantedAuthority;
@@ -41,6 +42,7 @@
4142
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
4243
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
4344
@JsonIgnoreProperties({ "authenticated" })
45+
@NullUnmarked
4446
class Saml2AuthenticationMixin {
4547

4648
@JsonCreator

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/jackson/Saml2ErrorMixin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.fasterxml.jackson.annotation.JsonCreator;
2121
import com.fasterxml.jackson.annotation.JsonProperty;
2222
import com.fasterxml.jackson.annotation.JsonTypeInfo;
23+
import org.jspecify.annotations.NullUnmarked;
2324

2425
import org.springframework.security.saml2.core.Saml2Error;
2526

@@ -35,6 +36,7 @@
3536
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
3637
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
3738
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
39+
@NullUnmarked
3840
class Saml2ErrorMixin {
3941

4042
@JsonCreator

0 commit comments

Comments
 (0)