Skip to content

Commit 12f2622

Browse files
committed
Test NimbusJwtEncoder & NimbusJwtDecoder symmetrically
This test encodes an JWT with NimbusJwtEncoder, and then decodes it with NimbusJwtDecoder. This test will fail when NimbusJwtEncoder emits a JWT with a wrong `typ' parameter in the header, as NimbusJwtDecoder validates the JWT with JwtTypeValidator by default. It may be beneficial for finding out other similiar bugs too. Signed-off-by: Ziqin Wang <[email protected]>
1 parent 29b9dc6 commit 12f2622

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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+
package org.springframework.security.oauth2.jwt;
18+
19+
import java.security.GeneralSecurityException;
20+
import java.security.KeyPair;
21+
import java.security.KeyPairGenerator;
22+
import java.security.interfaces.ECPrivateKey;
23+
import java.security.interfaces.ECPublicKey;
24+
import java.security.interfaces.RSAPrivateKey;
25+
import java.security.interfaces.RSAPublicKey;
26+
import java.security.spec.ECGenParameterSpec;
27+
import java.util.Objects;
28+
import java.util.Set;
29+
30+
import javax.crypto.KeyGenerator;
31+
import javax.crypto.SecretKey;
32+
33+
import com.nimbusds.jose.JOSEException;
34+
import com.nimbusds.jose.crypto.impl.ECDSA;
35+
import com.nimbusds.jose.jwk.Curve;
36+
import com.nimbusds.jose.jwk.ECKey;
37+
import com.nimbusds.jose.jwk.JWK;
38+
import com.nimbusds.jose.jwk.JWKSet;
39+
import com.nimbusds.jose.jwk.KeyOperation;
40+
import com.nimbusds.jose.jwk.KeyUse;
41+
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
42+
import org.junit.jupiter.api.Test;
43+
44+
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
45+
46+
import static org.assertj.core.api.Assertions.assertThat;
47+
48+
/**
49+
* Use {@link NimbusJwtDecoder} to decode JWT's encoded with {@link NimbusJwtEncoder}
50+
*
51+
* @author Ziqin Wang
52+
*/
53+
public class NimbusJwtEncoderDecoderTests {
54+
55+
@Test
56+
public void encodeAndDecodeHS256() throws GeneralSecurityException {
57+
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA256");
58+
SecretKey secretKey = keyGenerator.generateKey();
59+
60+
NimbusJwtEncoder jwtEncoder = NimbusJwtEncoder.withSecretKey(secretKey).build();
61+
JwtClaimsSet claims = TestJwtClaimsSets.jwtClaimsSet().build();
62+
String jwt = jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
63+
64+
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withSecretKey(secretKey).build();
65+
Jwt decodedJwt = jwtDecoder.decode(jwt);
66+
67+
assertThat(decodedJwt.getSubject()).isEqualTo("subject");
68+
}
69+
70+
@Test
71+
public void encodeAndDecodeRS256() throws GeneralSecurityException {
72+
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
73+
keyPairGenerator.initialize(2048);
74+
KeyPair keyPair = keyPairGenerator.generateKeyPair();
75+
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
76+
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
77+
78+
NimbusJwtEncoder jwtEncoder = NimbusJwtEncoder.withKeyPair(publicKey, privateKey).build();
79+
JwtClaimsSet claims = TestJwtClaimsSets.jwtClaimsSet().build();
80+
String jwt = jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
81+
82+
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withPublicKey(publicKey).build();
83+
Jwt decodedJwt = jwtDecoder.decode(jwt);
84+
85+
assertThat(decodedJwt.getSubject()).isEqualTo("subject");
86+
}
87+
88+
@Test
89+
public void encodeAndDecodeES256() throws GeneralSecurityException, JOSEException {
90+
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
91+
keyPairGenerator.initialize(new ECGenParameterSpec("secp256r1"));
92+
KeyPair keyPair = keyPairGenerator.generateKeyPair();
93+
ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
94+
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
95+
96+
NimbusJwtEncoder jwtEncoder = NimbusJwtEncoder.withKeyPair(publicKey, privateKey).build();
97+
JwtClaimsSet claims = TestJwtClaimsSets.jwtClaimsSet().build();
98+
String jwt = jwtEncoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
99+
100+
Curve curve = Curve.forECParameterSpec(publicKey.getParams());
101+
JWK jwk = new ECKey.Builder(curve, publicKey).keyOperations(Set.of(KeyOperation.VERIFY))
102+
.keyUse(KeyUse.SIGNATURE)
103+
.algorithm(ECDSA.resolveAlgorithm(curve))
104+
.keyIDFromThumbprint()
105+
.build();
106+
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSource(new ImmutableJWKSet<>(new JWKSet(jwk)))
107+
.jwsAlgorithm(Objects.requireNonNull(SignatureAlgorithm.from(jwk.getAlgorithm().getName())))
108+
.build();
109+
Jwt decodedJwt = jwtDecoder.decode(jwt);
110+
111+
assertThat(decodedJwt.getSubject()).isEqualTo("subject");
112+
}
113+
114+
}

0 commit comments

Comments
 (0)