Skip to content

Commit acfe4bd

Browse files
jzheauxBudlee
andcommitted
Polish to Avoid NPE
Issue gh-5648 Co-authored-by: MattyA <[email protected]>
1 parent 48a0514 commit acfe4bd

File tree

4 files changed

+60
-5
lines changed

4 files changed

+60
-5
lines changed

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.text.ParseException;
2222
import java.time.Instant;
2323
import java.util.Arrays;
24+
import java.util.Collection;
2425
import java.util.Collections;
2526
import java.util.LinkedHashMap;
2627
import java.util.Map;
@@ -47,10 +48,12 @@
4748
import org.springframework.http.MediaType;
4849
import org.springframework.http.RequestEntity;
4950
import org.springframework.http.ResponseEntity;
51+
import org.springframework.security.oauth2.core.OAuth2Error;
5052
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
5153
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
5254
import org.springframework.security.oauth2.jose.jws.JwsAlgorithms;
5355
import org.springframework.util.Assert;
56+
import org.springframework.util.StringUtils;
5457
import org.springframework.web.client.RestOperations;
5558
import org.springframework.web.client.RestTemplate;
5659

@@ -190,9 +193,17 @@ private Jwt createJwt(String token, JWT parsedJwt) {
190193
private Jwt validateJwt(Jwt jwt){
191194
OAuth2TokenValidatorResult result = this.jwtValidator.validate(jwt);
192195
if (result.hasErrors()) {
193-
String description = result.getErrors().iterator().next().getDescription();
196+
Collection<OAuth2Error> errors = result.getErrors();
197+
String validationErrorString = "Unable to validate Jwt";
198+
for (OAuth2Error oAuth2Error : errors) {
199+
if (!StringUtils.isEmpty(oAuth2Error.getDescription())) {
200+
validationErrorString = String.format(
201+
DECODING_ERROR_MESSAGE_TEMPLATE, oAuth2Error.getDescription());
202+
break;
203+
}
204+
}
194205
throw new JwtValidationException(
195-
String.format(DECODING_ERROR_MESSAGE_TEMPLATE, description),
206+
validationErrorString,
196207
result.getErrors());
197208
}
198209

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

+13-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.security.interfaces.RSAPublicKey;
1919
import java.time.Instant;
20+
import java.util.Collection;
2021
import java.util.LinkedHashMap;
2122
import java.util.List;
2223
import java.util.Map;
@@ -40,10 +41,12 @@
4041
import com.nimbusds.jwt.proc.JWTProcessor;
4142
import reactor.core.publisher.Mono;
4243

44+
import org.springframework.security.oauth2.core.OAuth2Error;
4345
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
4446
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
4547
import org.springframework.security.oauth2.jose.jws.JwsAlgorithms;
4648
import org.springframework.util.Assert;
49+
import org.springframework.util.StringUtils;
4750

4851
/**
4952
* An implementation of a {@link ReactiveJwtDecoder} that &quot;decodes&quot; a
@@ -184,9 +187,16 @@ private Jwt createJwt(JWT parsedJwt, JWTClaimsSet jwtClaimsSet) {
184187
private Jwt validateJwt(Jwt jwt) {
185188
OAuth2TokenValidatorResult result = this.jwtValidator.validate(jwt);
186189

187-
if ( result.hasErrors() ) {
188-
String message = result.getErrors().iterator().next().getDescription();
189-
throw new JwtValidationException(message, result.getErrors());
190+
if (result.hasErrors()) {
191+
Collection<OAuth2Error> errors = result.getErrors();
192+
String validationErrorString = "Unable to validate Jwt";
193+
for (OAuth2Error oAuth2Error : errors) {
194+
if (!StringUtils.isEmpty(oAuth2Error.getDescription())) {
195+
validationErrorString = oAuth2Error.getDescription();
196+
break;
197+
}
198+
}
199+
throw new JwtValidationException(validationErrorString, errors);
190200
}
191201

192202
return jwt;

oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderJwkSupportTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.junit.Test;
3434
import org.junit.runner.RunWith;
3535
import org.mockito.ArgumentCaptor;
36+
import org.mockito.Mockito;
3637
import org.powermock.core.classloader.annotations.PowerMockIgnore;
3738
import org.powermock.core.classloader.annotations.PrepareForTest;
3839
import org.powermock.modules.junit4.PowerMockRunner;
@@ -241,6 +242,22 @@ public void decodeWhenJwtValidationHasTwoErrorsThenJwtExceptionMessageShowsFirst
241242
}
242243
}
243244

245+
@Test
246+
public void decodeWhenReadingErrorPickTheFirstErrorMessage() {
247+
OAuth2TokenValidator<Jwt> jwtValidator = mock(OAuth2TokenValidator.class);
248+
this.jwtDecoder.setJwtValidator(jwtValidator);
249+
250+
OAuth2Error errorEmpty = new OAuth2Error("mock-error", "", "mock-uri");
251+
OAuth2Error error = new OAuth2Error("mock-error", "mock-description", "mock-uri");
252+
OAuth2Error error2 = new OAuth2Error("mock-error-second", "mock-description-second", "mock-uri-second");
253+
OAuth2TokenValidatorResult result = OAuth2TokenValidatorResult.failure(errorEmpty, error, error2);
254+
Mockito.when(jwtValidator.validate(any(Jwt.class))).thenReturn(result);
255+
256+
Assertions.assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT))
257+
.isInstanceOf(JwtValidationException.class)
258+
.hasMessageContaining("mock-description");
259+
}
260+
244261
@Test
245262
public void decodeWhenUsingSignedJwtThenReturnsClaimsGivenByClaimSetConverter() throws Exception {
246263
try ( MockWebServer server = new MockWebServer() ) {

oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoderTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,23 @@ public void decodeWhenUsingCustomValidatorThenValidatorIsInvoked() {
177177
.hasMessageContaining("mock-description");
178178
}
179179

180+
181+
@Test
182+
public void decodeWhenReadingErrorPickTheFirstErrorMessage() {
183+
OAuth2TokenValidator<Jwt> jwtValidator = mock(OAuth2TokenValidator.class);
184+
this.decoder.setJwtValidator(jwtValidator);
185+
186+
OAuth2Error errorEmpty = new OAuth2Error("mock-error", "", "mock-uri");
187+
OAuth2Error error = new OAuth2Error("mock-error", "mock-description", "mock-uri");
188+
OAuth2Error error2 = new OAuth2Error("mock-error-second", "mock-description-second", "mock-uri-second");
189+
OAuth2TokenValidatorResult result = OAuth2TokenValidatorResult.failure(errorEmpty, error, error2);
190+
when(jwtValidator.validate(any(Jwt.class))).thenReturn(result);
191+
192+
assertThatCode(() -> this.decoder.decode(this.messageReadToken).block())
193+
.isInstanceOf(JwtValidationException.class)
194+
.hasMessageContaining("mock-description");
195+
}
196+
180197
@Test
181198
public void setJwtValidatorWhenGivenNullThrowsIllegalArgumentException() {
182199
assertThatCode(() -> this.decoder.setJwtValidator(null))

0 commit comments

Comments
 (0)