Skip to content

Commit 22a9858

Browse files
committed
Enable null-safety in spring-security-oauth2-jose
Closes gh-17821
1 parent 78f762f commit 22a9858

File tree

25 files changed

+178
-102
lines changed

25 files changed

+178
-102
lines changed

config/src/test/kotlin/org/springframework/security/config/annotation/web/OAuth2ResourceServerDslTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class OAuth2ResourceServerDslTests {
147147
}
148148

149149
class MockJwtDecoder: JwtDecoder {
150-
override fun decode(token: String?): Jwt {
150+
override fun decode(token: String): Jwt {
151151
return Jwt.withTokenValue("token")
152152
.header("alg", "none")
153153
.claim(SUB, "user")

config/src/test/kotlin/org/springframework/security/config/annotation/web/oauth2/resourceserver/JwtDslTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class JwtDslTests {
207207
}
208208

209209
class MockJwtDecoder: JwtDecoder {
210-
override fun decode(token: String?): Jwt {
210+
override fun decode(token: String): Jwt {
211211
return Jwt.withTokenValue("some tokenValue").build()
212212
}
213213
}

config/src/test/kotlin/org/springframework/security/config/web/server/ServerJwtDslTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ class ServerJwtDslTests {
168168
}
169169

170170
class NullReactiveJwtDecoder: ReactiveJwtDecoder {
171-
override fun decode(token: String?): Mono<Jwt> {
171+
override fun decode(token: String): Mono<Jwt> {
172172
return Mono.empty()
173173
}
174174
}

docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/oauth2/resourceserver/customuserdetailsservice/UserDetailsJwtPrincipalConverter.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@ import org.springframework.stereotype.Component
2929
class UserDetailsJwtPrincipalConverter(private val users: UserDetailsService) : Converter<Jwt, OAuth2AuthenticatedPrincipal> {
3030

3131
override fun convert(jwt: Jwt): OAuth2AuthenticatedPrincipal {
32-
val user = users.loadUserByUsername(jwt.subject)
32+
val subject = jwt.subject ?: throw IllegalArgumentException("JWT subject is required")
33+
val user = users.loadUserByUsername(subject)
3334
return JwtUser(jwt, user)
3435
}
3536

3637
private class JwtUser(private val jwt: Jwt, user: UserDetails) :
3738
User(user.username, user.password, user.isEnabled, user.isAccountNonExpired, user.isCredentialsNonExpired, user.isAccountNonLocked, user.authorities),
3839
OAuth2AuthenticatedPrincipal {
3940

40-
override fun getName(): String = jwt.subject
41+
override fun getName(): String = jwt.subject ?: ""
4142

4243
override fun getAttributes(): Map<String, Any> = jwt.claims
4344

oauth2/oauth2-jose/spring-security-oauth2-jose.gradle

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
plugins {
2+
id 'javadoc-warnings-error'
3+
id 'security-nullability'
4+
}
5+
16
apply plugin: 'io.spring.convention.spring-module'
2-
apply plugin: 'javadoc-warnings-error'
37

48
dependencies {
59
management platform(project(":spring-security-dependencies"))

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/MacAlgorithm.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.oauth2.jose.jws;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
/**
2022
* An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA)
2123
* specification and used by JSON Web Signature (JWS) to create a MAC of the contents of
@@ -69,7 +71,7 @@ public String getName() {
6971
* @param name the algorithm name
7072
* @return the resolved {@code MacAlgorithm}, or {@code null} if not found
7173
*/
72-
public static MacAlgorithm from(String name) {
74+
public static @Nullable MacAlgorithm from(String name) {
7375
for (MacAlgorithm algorithm : values()) {
7476
if (algorithm.getName().equals(name)) {
7577
return algorithm;

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/SignatureAlgorithm.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.oauth2.jose.jws;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
/**
2022
* An enumeration of the cryptographic algorithms defined by the JSON Web Algorithms (JWA)
2123
* specification and used by JSON Web Signature (JWS) to digitally sign the contents of
@@ -99,7 +101,7 @@ public String getName() {
99101
* @param name the algorithm name
100102
* @return the resolved {@code SignatureAlgorithm}, or {@code null} if not found
101103
*/
102-
public static SignatureAlgorithm from(String name) {
104+
public static @Nullable SignatureAlgorithm from(String name) {
103105
for (SignatureAlgorithm value : values()) {
104106
if (value.getName().equals(name)) {
105107
return value;

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jose/jws/package-info.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@
1717
/**
1818
* Core classes and interfaces providing support for JSON Web Signature (JWS).
1919
*/
20+
@NullMarked
2021
package org.springframework.security.oauth2.jose.jws;
22+
23+
import org.jspecify.annotations.NullMarked;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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 classes and interfaces providing support for JavaScript Object Signing and
19+
* Encryption (JOSE).
20+
*/
21+
@NullMarked
22+
package org.springframework.security.oauth2.jose;
23+
24+
import org.jspecify.annotations.NullMarked;

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofContext.java

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

1919
import java.net.URI;
2020

21-
import org.springframework.lang.Nullable;
21+
import org.jspecify.annotations.Nullable;
22+
2223
import org.springframework.security.oauth2.core.OAuth2Token;
2324
import org.springframework.util.Assert;
2425

@@ -38,7 +39,7 @@ public final class DPoPProofContext {
3839

3940
private final String targetUri;
4041

41-
private final OAuth2Token accessToken;
42+
private final @Nullable OAuth2Token accessToken;
4243

4344
private DPoPProofContext(String dPoPProof, String method, String targetUri, @Nullable OAuth2Token accessToken) {
4445
this.dPoPProof = dPoPProof;
@@ -82,8 +83,7 @@ public String getTargetUri() {
8283
* {@code null}
8384
*/
8485
@SuppressWarnings("unchecked")
85-
@Nullable
86-
public <T extends OAuth2Token> T getAccessToken() {
86+
public @Nullable <T extends OAuth2Token> T getAccessToken() {
8787
return (T) this.accessToken;
8888
}
8989

@@ -103,11 +103,11 @@ public static final class Builder {
103103

104104
private String dPoPProof;
105105

106-
private String method;
106+
private @Nullable String method;
107107

108-
private String targetUri;
108+
private @Nullable String targetUri;
109109

110-
private OAuth2Token accessToken;
110+
private @Nullable OAuth2Token accessToken;
111111

112112
private Builder(String dPoPProof) {
113113
Assert.hasText(dPoPProof, "dPoPProof cannot be empty");
@@ -144,7 +144,7 @@ public Builder targetUri(String targetUri) {
144144
* request
145145
* @return the {@link Builder}
146146
*/
147-
public Builder accessToken(OAuth2Token accessToken) {
147+
public Builder accessToken(@Nullable OAuth2Token accessToken) {
148148
this.accessToken = accessToken;
149149
return this;
150150
}
@@ -154,13 +154,13 @@ public Builder accessToken(OAuth2Token accessToken) {
154154
* @return a {@link DPoPProofContext}
155155
*/
156156
public DPoPProofContext build() {
157+
Assert.hasText(this.method, "method cannot be empty");
158+
Assert.hasText(this.targetUri, "targetUri cannot be empty");
157159
validate();
158160
return new DPoPProofContext(this.dPoPProof, this.method, this.targetUri, this.accessToken);
159161
}
160162

161163
private void validate() {
162-
Assert.hasText(this.method, "method cannot be empty");
163-
Assert.hasText(this.targetUri, "targetUri cannot be empty");
164164
if (!"GET".equals(this.method) && !"HEAD".equals(this.method) && !"POST".equals(this.method)
165165
&& !"PUT".equals(this.method) && !"PATCH".equals(this.method) && !"DELETE".equals(this.method)
166166
&& !"OPTIONS".equals(this.method) && !"TRACE".equals(this.method)) {

0 commit comments

Comments
 (0)