Skip to content

Commit d2c3b9d

Browse files
committed
Handle failed JWT signature verification
Issue spring-atticgh-1522 Fixes spring-atticgh-1852
1 parent 68a87b9 commit d2c3b9d

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,13 @@ protected Map<String, Object> decode(String token) {
121121

122122
// Verify signature
123123
SignatureVerifier verifier = jwkDefinitionHolder.getSignatureVerifier();
124-
Jwt jwt = JwtHelper.decode(token);
125-
jwt.verifySignature(verifier);
124+
Jwt jwt;
125+
try {
126+
jwt = JwtHelper.decode(token);
127+
jwt.verifySignature(verifier);
128+
} catch (Exception ex) {
129+
throw new InvalidTokenException("Failed to decode/verify JWT/JWS", ex);
130+
}
126131

127132
Map<String, Object> claims = this.jsonParser.parseMap(jwt.getClaims());
128133
if (claims.containsKey(EXP) && claims.get(EXP) instanceof Integer) {

spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverterTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.Map;
2525

2626
import static org.junit.Assert.assertNotNull;
27+
import static org.mockito.Matchers.any;
28+
import static org.mockito.Mockito.doThrow;
2729
import static org.mockito.Mockito.mock;
2830
import static org.mockito.Mockito.when;
2931
import static org.springframework.security.jwt.codec.Codecs.b64UrlEncode;
@@ -139,6 +141,26 @@ public void decodeWhenKidHeaderMissingButX5tHeaderPresentThenDecodeStillSucceeds
139141
assertNotNull(decodedJwt);
140142
}
141143

144+
// gh-1522, gh-1852
145+
@Test
146+
public void decodeWhenVerifySignatureFailsThenThrowInvalidTokenException() throws Exception {
147+
this.thrown.expect(InvalidTokenException.class);
148+
this.thrown.expectMessage("Failed to decode/verify JWT/JWS");
149+
JwkDefinition jwkDefinition = this.createRSAJwkDefinition("key-id-1", null, null);
150+
JwkDefinitionSource jwkDefinitionSource = mock(JwkDefinitionSource.class);
151+
JwkDefinitionSource.JwkDefinitionHolder jwkDefinitionHolder = mock(JwkDefinitionSource.JwkDefinitionHolder.class);
152+
SignatureVerifier signatureVerifier = mock(SignatureVerifier.class);
153+
when(jwkDefinitionHolder.getJwkDefinition()).thenReturn(jwkDefinition);
154+
when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1", null)).thenReturn(jwkDefinitionHolder);
155+
when(jwkDefinitionHolder.getSignatureVerifier()).thenReturn(signatureVerifier);
156+
doThrow(RuntimeException.class).when(signatureVerifier).verify(any(byte[].class), any(byte[].class));
157+
JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
158+
new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource);
159+
String jwt = createJwt(createJwtHeader("key-id-1", null, JwkDefinition.CryptoAlgorithm.RS256));
160+
String jws = jwt + "." + utf8Decode(b64UrlEncode("junkSignature".getBytes()));
161+
accessTokenConverter.decode(jws);
162+
}
163+
142164
private JwkDefinition createRSAJwkDefinition(String keyId, String x5t, JwkDefinition.CryptoAlgorithm algorithm) {
143165
return createRSAJwkDefinition(JwkDefinition.KeyType.RSA, keyId, x5t,
144166
JwkDefinition.PublicKeyUse.SIG, algorithm, "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL", "AQAB");

0 commit comments

Comments
 (0)