JAVA-26712 | jjwt update (#15344)

* JAVA-26712 | jjwt update

* removed unused related article

* JAVA-26712 | fix
This commit is contained in:
Gaetano Piazzolla 2023-12-10 22:39:11 +01:00 committed by GitHub
parent ddce8cd34e
commit f7205747ff
19 changed files with 82 additions and 72 deletions

View File

@ -1,7 +1,5 @@
## JHipster
This module contains articles about JHipster.
### Relevant articles:
This module contains articles about JHipster.
Relevant articles are listed in the nested module folders.

View File

@ -29,7 +29,7 @@
<javassist.version>3.21.0-GA</javassist.version>
<jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version>
<jjwt.version>0.12.3</jjwt.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>
@ -216,7 +216,7 @@
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>

View File

@ -70,7 +70,7 @@ public class TokenProvider {
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.setSigningKey(secretKey).build()
.parseClaimsJws(token)
.getBody();
@ -86,7 +86,7 @@ public class TokenProvider {
public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
Jwts.parser().setSigningKey(secretKey).build().parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
log.info("Invalid JWT signature.");

View File

@ -28,7 +28,7 @@
<javassist.version>3.21.0-GA</javassist.version>
<jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version>
<jjwt.version>0.12.3</jjwt.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>
@ -215,7 +215,7 @@
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>

View File

@ -70,7 +70,7 @@ public class TokenProvider {
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.setSigningKey(secretKey).build()
.parseClaimsJws(token)
.getBody();
@ -86,7 +86,7 @@ public class TokenProvider {
public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
Jwts.parser().setSigningKey(secretKey).build().parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
log.info("Invalid JWT signature.");

View File

@ -31,7 +31,7 @@
<javassist.version>3.21.0-GA</javassist.version>
<jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version>
<jjwt.version>0.12.3</jjwt.version>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>
@ -243,7 +243,7 @@
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>

View File

@ -70,7 +70,7 @@ public class TokenProvider {
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.setSigningKey(secretKey).build()
.parseClaimsJws(token)
.getBody();
@ -86,7 +86,7 @@ public class TokenProvider {
public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
Jwts.parser().setSigningKey(secretKey).build().parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
log.info("Invalid JWT signature.");

View File

@ -122,7 +122,7 @@
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
@ -897,7 +897,7 @@
<javassist.version>3.21.0-GA</javassist.version>
<jcache.version>1.0.0</jcache.version>
<jhipster.server.version>1.1.0</jhipster.server.version>
<jjwt.version>0.7.0</jjwt.version>
<jjwt.version>0.12.3</jjwt.version>
<jzlib.version>1.1.3</jzlib.version>
<liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
<liquibase-slf4j.version>2.0.0</liquibase-slf4j.version>

View File

@ -70,7 +70,7 @@ public class TokenProvider {
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.setSigningKey(secretKey).build()
.parseClaimsJws(token)
.getBody();
@ -86,7 +86,7 @@ public class TokenProvider {
public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
Jwts.parser().setSigningKey(secretKey).build().parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
log.info("Invalid JWT signature.");

View File

@ -54,8 +54,8 @@
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<!-- persistence -->
<dependency>

View File

@ -30,7 +30,7 @@ public class AuthenticationService {
if (token != null) {
String user = Jwts.parser()
.setSigningKey(SIGNINGKEY)
.parseClaimsJws(token.replace(PREFIX, ""))
.build().parseClaimsJws(token.replace(PREFIX, ""))
.getBody()
.getSubject();
if (user != null) {
@ -48,9 +48,11 @@ public class AuthenticationService {
}
String tenant = Jwts.parser()
.setSigningKey(SIGNINGKEY)
.parseClaimsJws(token.replace(PREFIX, ""))
.build().parseClaimsJws(token.replace(PREFIX, ""))
.getBody()
.getAudience();
.getAudience()
.iterator()
.next();
return tenant;
}
}

View File

@ -35,13 +35,23 @@
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
</dependency>
</dependencies>
<properties>
<jjwt.version>0.7.0</jjwt.version>
<jjwt.version>0.12.3</jjwt.version>
</properties>
</project>

View File

@ -66,7 +66,7 @@ public class WebSecurityConfig {
// CsrfFilter already made sure the token matched. Here, we'll make sure it's not expired
try {
Jwts.parser()
.setSigningKeyResolver(secretService.getSigningKeyResolver())
.setSigningKeyResolver(secretService.getSigningKeyResolver()).build()
.parseClaimsJws(token.getToken());
} catch (JwtException e) {
// most likely an ExpiredJwtException, but this will handle any

View File

@ -4,7 +4,7 @@ import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.compression.CompressionCodecs;
import io.jsonwebtoken.impl.compression.DeflateCompressionAlgorithm;
import io.jsonwebtoken.jjwtfun.model.JwtResponse;
import io.jsonwebtoken.jjwtfun.service.SecretService;
import org.springframework.beans.factory.annotation.Autowired;
@ -38,7 +38,7 @@ public class DynamicJWTController extends BaseController {
public JwtResponse dynamicBuildercompress(@RequestBody Map<String, Object> claims) throws UnsupportedEncodingException {
String jws = Jwts.builder()
.setClaims(claims)
.compressWith(CompressionCodecs.DEFLATE)
.compressWith(new DeflateCompressionAlgorithm())
.signWith(SignatureAlgorithm.HS256, secretService.getHS256SecretBytes())
.compact();
return new JwtResponse(jws);

View File

@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@ -23,7 +24,7 @@ public class SecretsController extends BaseController {
}
@RequestMapping(value = "/refresh-secrets", method = GET)
public Map<String, String> refreshSecrets() {
public Map<String, String> refreshSecrets() throws NoSuchAlgorithmException {
return secretService.refreshSecrets();
}

View File

@ -42,7 +42,7 @@ public class StaticJWTController extends BaseController {
public JwtResponse parser(@RequestParam String jwt) throws UnsupportedEncodingException {
Jws<Claims> jws = Jwts.parser()
.setSigningKeyResolver(secretService.getSigningKeyResolver())
.setSigningKeyResolver(secretService.getSigningKeyResolver()).build()
.parseClaimsJws(jwt);
return new JwtResponse(jws);
@ -53,7 +53,7 @@ public class StaticJWTController extends BaseController {
Jws<Claims> jws = Jwts.parser()
.requireIssuer("Stormpath")
.require("hasMotorcycle", true)
.setSigningKeyResolver(secretService.getSigningKeyResolver())
.setSigningKeyResolver(secretService.getSigningKeyResolver()).build()
.parseClaimsJws(jwt);
return new JwtResponse(jws);

View File

@ -6,12 +6,14 @@ import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SigningKeyResolver;
import io.jsonwebtoken.SigningKeyResolverAdapter;
import io.jsonwebtoken.impl.TextCodec;
import io.jsonwebtoken.impl.crypto.MacProvider;
import io.jsonwebtoken.lang.Assert;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
@ -28,7 +30,7 @@ public class SecretService {
};
@PostConstruct
public void setup() {
public void setup() throws NoSuchAlgorithmException {
refreshSecrets();
}
@ -42,32 +44,34 @@ public class SecretService {
public void setSecrets(Map<String, String> secrets) {
Assert.notNull(secrets);
Assert.hasText(secrets.get(SignatureAlgorithm.HS256.getValue()));
Assert.hasText(secrets.get(SignatureAlgorithm.HS384.getValue()));
Assert.hasText(secrets.get(SignatureAlgorithm.HS512.getValue()));
Assert.hasText(secrets.get(SignatureAlgorithm.HS256.getJcaName()));
Assert.hasText(secrets.get(SignatureAlgorithm.HS384.getJcaName()));
Assert.hasText(secrets.get(SignatureAlgorithm.HS512.getJcaName()));
this.secrets = secrets;
}
public byte[] getHS256SecretBytes() {
return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS256.getValue()));
return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS256.getJcaName()));
}
public byte[] getHS384SecretBytes() {
return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS384.getValue()));
return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS384.getJcaName()));
}
public byte[] getHS512SecretBytes() {
return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS512.getValue()));
return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS512.getJcaName()));
}
public Map<String, String> refreshSecrets() {
SecretKey key = MacProvider.generateKey(SignatureAlgorithm.HS256);
secrets.put(SignatureAlgorithm.HS256.getValue(), TextCodec.BASE64.encode(key.getEncoded()));
key = MacProvider.generateKey(SignatureAlgorithm.HS384);
secrets.put(SignatureAlgorithm.HS384.getValue(), TextCodec.BASE64.encode(key.getEncoded()));
key = MacProvider.generateKey(SignatureAlgorithm.HS512);
secrets.put(SignatureAlgorithm.HS512.getValue(), TextCodec.BASE64.encode(key.getEncoded()));
public Map<String, String> refreshSecrets() throws NoSuchAlgorithmException {
SecretKey key = KeyGenerator.getInstance(SignatureAlgorithm.HS256.getJcaName()).generateKey();
secrets.put(SignatureAlgorithm.HS256.getJcaName(), TextCodec.BASE64.encode(key.getEncoded()));
key = KeyGenerator.getInstance(SignatureAlgorithm.HS384.getJcaName()).generateKey();
secrets.put(SignatureAlgorithm.HS384.getJcaName(), TextCodec.BASE64.encode(key.getEncoded()));
key = KeyGenerator.getInstance(SignatureAlgorithm.HS512.getJcaName()).generateKey();
secrets.put(SignatureAlgorithm.HS512.getJcaName(), TextCodec.BASE64.encode(key.getEncoded()));
return secrets;
}
}

View File

@ -1,12 +1,14 @@
package io.jsonwebtoken.jjwtfun.util;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import static io.jsonwebtoken.SignatureAlgorithm.HS256;
public class JWTDecoderUtil {
@ -21,26 +23,19 @@ public class JWTDecoderUtil {
return header + " " + payload;
}
public static String decodeJWTToken(String token, String secretKey) throws Exception {
Base64.Decoder decoder = Base64.getUrlDecoder();
public static boolean isTokenValid(String token, String secretKey) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName());
String[] chunks = token.split("\\.");
JwtParser jwtParser = Jwts.parser()
.verifyWith(secretKeySpec)
.build();
String header = new String(decoder.decode(chunks[0]));
String payload = new String(decoder.decode(chunks[1]));
String tokenWithoutSignature = chunks[0] + "." + chunks[1];
String signature = chunks[2];
SignatureAlgorithm sa = HS256;
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), sa.getJcaName());
DefaultJwtSignatureValidator validator = new DefaultJwtSignatureValidator(sa, secretKeySpec);
if (!validator.isValid(tokenWithoutSignature, signature)) {
throw new Exception("Could not verify JWT token integrity!");
try {
jwtParser.parse(token);
} catch (Exception e) {
throw new Exception("Could not verify JWT token integrity!", e);
}
return header + " " + payload;
return true;
}
}

View File

@ -1,16 +1,16 @@
package io.jsonwebtoken.jjwtfun.util;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertTrue;
class JWTDecoderUtilUnitTest {
private final static String SIMPLE_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9";
private final static String SIGNED_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.qH7Zj_m3kY69kxhaQXTa-ivIpytKXXjZc1ZSmapZnGE";
private final static String SIGNED_TOKEN = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJhZWxkdW5nIFVzZXIiLCJpYXQiOjE1MTYyMzkwMjJ9.6h_QYBTbyKxfMq3TGiAhVI416rctV0c0SpzWxVm-0-Y";
@Test
void givenSimpleToken_whenDecoding_thenStringOfHeaderPayloadAreReturned() {
@ -20,13 +20,13 @@ class JWTDecoderUtilUnitTest {
@Test
void givenSignedToken_whenDecodingWithInvalidSecret_thenIntegrityIsNotValidated() {
assertThatThrownBy(() -> JWTDecoderUtil.decodeJWTToken(SIGNED_TOKEN, "BAD_SECRET"))
assertThatThrownBy(() -> JWTDecoderUtil.
isTokenValid(SIGNED_TOKEN, "BAD_SECRET"))
.hasMessage("Could not verify JWT token integrity!");
}
@Test
void givenSignedToken_whenDecodingWithValidSecret_thenIntegrityIsValidated() throws Exception {
assertThat(JWTDecoderUtil.decodeJWTToken(SIGNED_TOKEN, "MySecretKey"))
.contains("Baeldung User");
assertTrue(JWTDecoderUtil.isTokenValid(SIGNED_TOKEN, "randomSecretWithSome!!CharacterS!"));
}
}