Skip to content

Commit 510d1b8

Browse files
jzheauxBudlee
andcommitted
Polish to Avoid NPE
Issue gh-5648 Co-authored-by: MattyA <[email protected]>
1 parent 2f80b8a commit 510d1b8

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

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

+13-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.security.interfaces.RSAPublicKey;
2323
import java.text.ParseException;
2424
import java.util.Arrays;
25+
import java.util.Collection;
2526
import java.util.Collections;
2627
import java.util.HashMap;
2728
import java.util.HashSet;
@@ -54,11 +55,13 @@
5455
import org.springframework.http.MediaType;
5556
import org.springframework.http.RequestEntity;
5657
import org.springframework.http.ResponseEntity;
58+
import org.springframework.security.oauth2.core.OAuth2Error;
5759
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
5860
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
5961
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
6062
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
6163
import org.springframework.util.Assert;
64+
import org.springframework.util.StringUtils;
6265
import org.springframework.web.client.RestOperations;
6366
import org.springframework.web.client.RestTemplate;
6467

@@ -164,9 +167,17 @@ private Jwt createJwt(String token, JWT parsedJwt) {
164167
private Jwt validateJwt(Jwt jwt){
165168
OAuth2TokenValidatorResult result = this.jwtValidator.validate(jwt);
166169
if (result.hasErrors()) {
167-
String description = result.getErrors().iterator().next().getDescription();
170+
Collection<OAuth2Error> errors = result.getErrors();
171+
String validationErrorString = "Unable to validate Jwt";
172+
for (OAuth2Error oAuth2Error : errors) {
173+
if (!StringUtils.isEmpty(oAuth2Error.getDescription())) {
174+
validationErrorString = String.format(
175+
DECODING_ERROR_MESSAGE_TEMPLATE, oAuth2Error.getDescription());
176+
break;
177+
}
178+
}
168179
throw new JwtValidationException(
169-
String.format(DECODING_ERROR_MESSAGE_TEMPLATE, description),
180+
validationErrorString,
170181
result.getErrors());
171182
}
172183

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

+13-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.security.oauth2.jwt;
1717

1818
import java.security.interfaces.RSAPublicKey;
19+
import java.util.Collection;
1920
import java.util.Collections;
2021
import java.util.HashMap;
2122
import java.util.HashSet;
@@ -51,12 +52,14 @@
5152
import reactor.core.publisher.Mono;
5253

5354
import org.springframework.core.convert.converter.Converter;
55+
import org.springframework.security.oauth2.core.OAuth2Error;
5456
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
5557
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
5658
import org.springframework.security.oauth2.jose.jws.JwsAlgorithm;
5759
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
5860
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
5961
import org.springframework.util.Assert;
62+
import org.springframework.util.StringUtils;
6063
import org.springframework.web.reactive.function.client.WebClient;
6164

6265
/**
@@ -172,10 +175,16 @@ private Jwt createJwt(JWT parsedJwt, JWTClaimsSet jwtClaimsSet) {
172175

173176
private Jwt validateJwt(Jwt jwt) {
174177
OAuth2TokenValidatorResult result = this.jwtValidator.validate(jwt);
175-
176-
if ( result.hasErrors() ) {
177-
String message = result.getErrors().iterator().next().getDescription();
178-
throw new JwtValidationException(message, result.getErrors());
178+
if (result.hasErrors()) {
179+
Collection<OAuth2Error> errors = result.getErrors();
180+
String validationErrorString = "Unable to validate Jwt";
181+
for (OAuth2Error oAuth2Error : errors) {
182+
if (!StringUtils.isEmpty(oAuth2Error.getDescription())) {
183+
validationErrorString = oAuth2Error.getDescription();
184+
break;
185+
}
186+
}
187+
throw new JwtValidationException(validationErrorString, errors);
179188
}
180189

181190
return jwt;

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

+16
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,22 @@ public void decodeWhenJwtValidationHasTwoErrorsThenJwtExceptionMessageShowsFirst
193193
.hasFieldOrPropertyWithValue("errors", Arrays.asList(firstFailure, secondFailure));
194194
}
195195

196+
@Test
197+
public void decodeWhenReadingErrorPickTheFirstErrorMessage() {
198+
OAuth2TokenValidator<Jwt> jwtValidator = mock(OAuth2TokenValidator.class);
199+
this.jwtDecoder.setJwtValidator(jwtValidator);
200+
201+
OAuth2Error errorEmpty = new OAuth2Error("mock-error", "", "mock-uri");
202+
OAuth2Error error = new OAuth2Error("mock-error", "mock-description", "mock-uri");
203+
OAuth2Error error2 = new OAuth2Error("mock-error-second", "mock-description-second", "mock-uri-second");
204+
OAuth2TokenValidatorResult result = OAuth2TokenValidatorResult.failure(errorEmpty, error, error2);
205+
when(jwtValidator.validate(any(Jwt.class))).thenReturn(result);
206+
207+
Assertions.assertThatCode(() -> this.jwtDecoder.decode(SIGNED_JWT))
208+
.isInstanceOf(JwtValidationException.class)
209+
.hasMessageContaining("mock-description");
210+
}
211+
196212
@Test
197213
public void decodeWhenUsingSignedJwtThenReturnsClaimsGivenByClaimSetConverter() {
198214
Converter<Map<String, Object>, Map<String, Object>> claimSetConverter = mock(Converter.class);

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

+16
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ public void decodeWhenUsingCustomValidatorThenValidatorIsInvoked() {
221221
.hasMessageContaining("mock-description");
222222
}
223223

224+
@Test
225+
public void decodeWhenReadingErrorPickTheFirstErrorMessage() {
226+
OAuth2TokenValidator<Jwt> jwtValidator = mock(OAuth2TokenValidator.class);
227+
this.decoder.setJwtValidator(jwtValidator);
228+
229+
OAuth2Error errorEmpty = new OAuth2Error("mock-error", "", "mock-uri");
230+
OAuth2Error error = new OAuth2Error("mock-error", "mock-description", "mock-uri");
231+
OAuth2Error error2 = new OAuth2Error("mock-error-second", "mock-description-second", "mock-uri-second");
232+
OAuth2TokenValidatorResult result = OAuth2TokenValidatorResult.failure(errorEmpty, error, error2);
233+
when(jwtValidator.validate(any(Jwt.class))).thenReturn(result);
234+
235+
assertThatCode(() -> this.decoder.decode(this.messageReadToken).block())
236+
.isInstanceOf(JwtValidationException.class)
237+
.hasMessageContaining("mock-description");
238+
}
239+
224240
@Test
225241
public void decodeWhenUsingSignedJwtThenReturnsClaimsGivenByClaimSetConverter() {
226242
Converter<Map<String, Object>, Map<String, Object>> claimSetConverter = mock(Converter.class);

0 commit comments

Comments
 (0)