Skip to content

Commit 0a991a9

Browse files
committed
Enable Null checking in spring-security-webauthn via JSpecify
Closes gh-17839
1 parent 3dbcf26 commit 0a991a9

File tree

46 files changed

+422
-153
lines changed

Some content is hidden

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

46 files changed

+422
-153
lines changed

webauthn/src/main/java/org/springframework/security/web/webauthn/aot/PublicKeyCredentialUserEntityRuntimeHints.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.security.web.webauthn.aot;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.aot.hint.RuntimeHints;
2022
import org.springframework.aot.hint.RuntimeHintsRegistrar;
2123
import org.springframework.jdbc.core.JdbcOperations;
@@ -33,7 +35,7 @@
3335
class PublicKeyCredentialUserEntityRuntimeHints implements RuntimeHintsRegistrar {
3436

3537
@Override
36-
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
38+
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
3739
hints.resources().registerPattern("org/springframework/security/user-entities-schema.sql");
3840
}
3941

webauthn/src/main/java/org/springframework/security/web/webauthn/aot/UserCredentialRuntimeHints.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.security.web.webauthn.aot;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.aot.hint.RuntimeHints;
2022
import org.springframework.aot.hint.RuntimeHintsRegistrar;
2123
import org.springframework.jdbc.core.JdbcOperations;
@@ -33,7 +35,7 @@
3335
class UserCredentialRuntimeHints implements RuntimeHintsRegistrar {
3436

3537
@Override
36-
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
38+
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
3739
hints.resources()
3840
.registerPattern("org/springframework/security/user-credentials-schema.sql")
3941
.registerPattern("org/springframework/security/user-credentials-schema-postgres.sql");
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+
* WebAuthn AOT support.
19+
*/
20+
@NullMarked
21+
package org.springframework.security.web.webauthn.aot;
22+
23+
import org.jspecify.annotations.NullMarked;

webauthn/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorAssertionResponse.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
import java.io.Serial;
2020

21+
import org.jspecify.annotations.Nullable;
22+
23+
import org.springframework.util.Assert;
24+
2125
/**
2226
* The <a href=
2327
* "https://www.w3.org/TR/webauthn-3/#authenticatorassertionresponse">AuthenticatorAssertionResponse</a>
@@ -47,12 +51,12 @@ public final class AuthenticatorAssertionResponse extends AuthenticatorResponse
4751

4852
private final Bytes signature;
4953

50-
private final Bytes userHandle;
54+
private final @Nullable Bytes userHandle;
5155

52-
private final Bytes attestationObject;
56+
private final @Nullable Bytes attestationObject;
5357

5458
private AuthenticatorAssertionResponse(Bytes clientDataJSON, Bytes authenticatorData, Bytes signature,
55-
Bytes userHandle, Bytes attestationObject) {
59+
@Nullable Bytes userHandle, @Nullable Bytes attestationObject) {
5660
super(clientDataJSON);
5761
this.authenticatorData = authenticatorData;
5862
this.signature = signature;
@@ -101,7 +105,7 @@ public Bytes getSignature() {
101105
* ceremony</a> is empty, and MAY return one otherwise.
102106
* @return the <a href="https://www.w3.org/TR/webauthn-3/#user-handle">user handle</a>
103107
*/
104-
public Bytes getUserHandle() {
108+
public @Nullable Bytes getUserHandle() {
105109
return this.userHandle;
106110
}
107111

@@ -113,7 +117,7 @@ public Bytes getUserHandle() {
113117
* object</a>, if the authenticator supports attestation in assertions.
114118
* @return the {@code attestationObject}
115119
*/
116-
public Bytes getAttestationObject() {
120+
public @Nullable Bytes getAttestationObject() {
117121
return this.attestationObject;
118122
}
119123

@@ -133,15 +137,15 @@ public static AuthenticatorAssertionResponseBuilder builder() {
133137
*/
134138
public static final class AuthenticatorAssertionResponseBuilder {
135139

136-
private Bytes authenticatorData;
140+
private @Nullable Bytes authenticatorData;
137141

138-
private Bytes signature;
142+
private @Nullable Bytes signature;
139143

140-
private Bytes userHandle;
144+
private @Nullable Bytes userHandle;
141145

142-
private Bytes attestationObject;
146+
private @Nullable Bytes attestationObject;
143147

144-
private Bytes clientDataJSON;
148+
private @Nullable Bytes clientDataJSON;
145149

146150
private AuthenticatorAssertionResponseBuilder() {
147151
}
@@ -201,6 +205,9 @@ public AuthenticatorAssertionResponseBuilder clientDataJSON(Bytes clientDataJSON
201205
* @return the {@link AuthenticatorAssertionResponse}
202206
*/
203207
public AuthenticatorAssertionResponse build() {
208+
Assert.notNull(this.clientDataJSON, "clientDataJSON cannot be null");
209+
Assert.notNull(this.authenticatorData, "authenticatorData cannot be null");
210+
Assert.notNull(this.signature, "signature cannot be null");
204211
return new AuthenticatorAssertionResponse(this.clientDataJSON, this.authenticatorData, this.signature,
205212
this.userHandle, this.attestationObject);
206213
}

webauthn/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorAttestationResponse.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.util.Arrays;
2020
import java.util.List;
2121

22+
import org.jspecify.annotations.Nullable;
23+
2224
/**
2325
* <a href=
2426
* "https://www.w3.org/TR/webauthn-3/#authenticatorattestationresponse">AuthenticatorAttestationResponse</a>
@@ -36,10 +38,10 @@ public final class AuthenticatorAttestationResponse extends AuthenticatorRespons
3638

3739
private final Bytes attestationObject;
3840

39-
private final List<AuthenticatorTransport> transports;
41+
private final @Nullable List<AuthenticatorTransport> transports;
4042

4143
private AuthenticatorAttestationResponse(Bytes clientDataJSON, Bytes attestationObject,
42-
List<AuthenticatorTransport> transports) {
44+
@Nullable List<AuthenticatorTransport> transports) {
4345
super(clientDataJSON);
4446
this.attestationObject = attestationObject;
4547
this.transports = transports;
@@ -63,7 +65,7 @@ public Bytes getAttestationObject() {
6365
* "https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponse-transports-slot">transports</a>
6466
* @return the transports
6567
*/
66-
public List<AuthenticatorTransport> getTransports() {
68+
public @Nullable List<AuthenticatorTransport> getTransports() {
6769
return this.transports;
6870
}
6971

@@ -83,10 +85,12 @@ public static AuthenticatorAttestationResponseBuilder builder() {
8385
*/
8486
public static final class AuthenticatorAttestationResponseBuilder {
8587

88+
@SuppressWarnings("NullAway.Init")
8689
private Bytes attestationObject;
8790

88-
private List<AuthenticatorTransport> transports;
91+
private @Nullable List<AuthenticatorTransport> transports;
8992

93+
@SuppressWarnings("NullAway.Init")
9094
private Bytes clientDataJSON;
9195

9296
private AuthenticatorAttestationResponseBuilder() {

webauthn/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorSelectionCriteria.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.security.web.webauthn.api;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
/**
2022
* <a href=
2123
* "https://www.w3.org/TR/webauthn-3/#dictdef-authenticatorselectioncriteria">AuthenticatorAttachment</a>
@@ -33,11 +35,11 @@
3335
*/
3436
public final class AuthenticatorSelectionCriteria {
3537

36-
private final AuthenticatorAttachment authenticatorAttachment;
38+
private final @Nullable AuthenticatorAttachment authenticatorAttachment;
3739

38-
private final ResidentKeyRequirement residentKey;
40+
private final @Nullable ResidentKeyRequirement residentKey;
3941

40-
private final UserVerificationRequirement userVerification;
42+
private final @Nullable UserVerificationRequirement userVerification;
4143

4244
// NOTE: There is no requireResidentKey property because it is only for backward
4345
// compatibility with WebAuthn Level 1
@@ -48,8 +50,8 @@ public final class AuthenticatorSelectionCriteria {
4850
* @param residentKey the resident key requirement
4951
* @param userVerification the user verification
5052
*/
51-
private AuthenticatorSelectionCriteria(AuthenticatorAttachment authenticatorAttachment,
52-
ResidentKeyRequirement residentKey, UserVerificationRequirement userVerification) {
53+
private AuthenticatorSelectionCriteria(@Nullable AuthenticatorAttachment authenticatorAttachment,
54+
@Nullable ResidentKeyRequirement residentKey, @Nullable UserVerificationRequirement userVerification) {
5355
this.authenticatorAttachment = authenticatorAttachment;
5456
this.residentKey = residentKey;
5557
this.userVerification = userVerification;
@@ -67,7 +69,7 @@ private AuthenticatorSelectionCriteria(AuthenticatorAttachment authenticatorAtta
6769
* Authenticator Attachment Modality</a>).
6870
* @return the authenticator attachment
6971
*/
70-
public AuthenticatorAttachment getAuthenticatorAttachment() {
72+
public @Nullable AuthenticatorAttachment getAuthenticatorAttachment() {
7173
return this.authenticatorAttachment;
7274
}
7375

@@ -81,7 +83,7 @@ public AuthenticatorAttachment getAuthenticatorAttachment() {
8183
* discoverable credential</a>.
8284
* @return the resident key requirement
8385
*/
84-
public ResidentKeyRequirement getResidentKey() {
86+
public @Nullable ResidentKeyRequirement getResidentKey() {
8587
return this.residentKey;
8688
}
8789

@@ -96,7 +98,7 @@ public ResidentKeyRequirement getResidentKey() {
9698
* operation.
9799
* @return the user verification requirement
98100
*/
99-
public UserVerificationRequirement getUserVerification() {
101+
public @Nullable UserVerificationRequirement getUserVerification() {
100102
return this.userVerification;
101103
}
102104

@@ -116,11 +118,11 @@ public static AuthenticatorSelectionCriteriaBuilder builder() {
116118
*/
117119
public static final class AuthenticatorSelectionCriteriaBuilder {
118120

119-
private AuthenticatorAttachment authenticatorAttachment;
121+
private @Nullable AuthenticatorAttachment authenticatorAttachment;
120122

121-
private ResidentKeyRequirement residentKey;
123+
private @Nullable ResidentKeyRequirement residentKey;
122124

123-
private UserVerificationRequirement userVerification;
125+
private @Nullable UserVerificationRequirement userVerification;
124126

125127
private AuthenticatorSelectionCriteriaBuilder() {
126128
}

webauthn/src/main/java/org/springframework/security/web/webauthn/api/Bytes.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.Arrays;
2323
import java.util.Base64;
2424

25+
import org.jspecify.annotations.Nullable;
26+
2527
import org.springframework.util.Assert;
2628

2729
/**
@@ -100,7 +102,7 @@ public static Bytes random() {
100102
* @param base64UrlString the base64 url string
101103
* @return the {@link Bytes}
102104
*/
103-
public static Bytes fromBase64(String base64UrlString) {
105+
public static Bytes fromBase64(@Nullable String base64UrlString) {
104106
byte[] bytes = DECODER.decode(base64UrlString);
105107
return new Bytes(bytes);
106108
}

webauthn/src/main/java/org/springframework/security/web/webauthn/api/CredentialRecord.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.time.Instant;
2020
import java.util.Set;
2121

22+
import org.jspecify.annotations.Nullable;
23+
2224
/**
2325
* Represents a <a href="https://www.w3.org/TR/webauthn-3/#credential-record">Credential
2426
* Record</a> that is stored by the Relying Party
@@ -35,7 +37,7 @@ public interface CredentialRecord {
3537
* "https://www.w3.org/TR/webauthn-3/#abstract-opdef-credential-record-type">credential.type</a>
3638
* @return
3739
*/
38-
PublicKeyCredentialType getCredentialType();
40+
@Nullable PublicKeyCredentialType getCredentialType();
3941

4042
/**
4143
* The <a href=
@@ -104,7 +106,7 @@ public interface CredentialRecord {
104106
* source was registered.
105107
* @return the attestationObject
106108
*/
107-
Bytes getAttestationObject();
109+
@Nullable Bytes getAttestationObject();
108110

109111
/**
110112
* The <a href=
@@ -113,7 +115,7 @@ public interface CredentialRecord {
113115
* source was registered.
114116
* @return
115117
*/
116-
Bytes getAttestationClientDataJSON();
118+
@Nullable Bytes getAttestationClientDataJSON();
117119

118120
/**
119121
* A human-readable label for this {@link CredentialRecord} assigned by the user.

0 commit comments

Comments
 (0)