diff --git a/pom.xml b/pom.xml
index 6f1d1a10..7bf8b93b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
2.21.1
0.2.2
1.13
- 0.11.5
+ 0.12.5
2021.0.9
0.27.0
1.8.0
diff --git a/src/main/java/jasper/security/Auth.java b/src/main/java/jasper/security/Auth.java
index 73df793c..ff7d380e 100644
--- a/src/main/java/jasper/security/Auth.java
+++ b/src/main/java/jasper/security/Auth.java
@@ -45,6 +45,7 @@
import java.util.Set;
import java.util.stream.Stream;
+import static io.jsonwebtoken.Jwts.claims;
import static jasper.config.JacksonConfiguration.dump;
import static jasper.domain.proj.HasOrigin.isSubOrigin;
import static jasper.repository.spec.OriginSpec.isOrigin;
@@ -936,7 +937,7 @@ public Claims getClaims() {
if (auth instanceof JwtAuthentication j) {
claims = j.getClaims();
} else {
- claims = new DefaultClaims();
+ claims = claims().build();
}
}
return claims;
diff --git a/src/main/java/jasper/security/jwt/JwkSigningKeyResolver.java b/src/main/java/jasper/security/jwt/JwkSigningKeyResolver.java
index 1b74202a..b26d2c87 100644
--- a/src/main/java/jasper/security/jwt/JwkSigningKeyResolver.java
+++ b/src/main/java/jasper/security/jwt/JwkSigningKeyResolver.java
@@ -36,7 +36,7 @@ public Key resolveSigningKey(JwsHeader header, Claims claims) {
}
@Override
- public Key resolveSigningKey(JwsHeader header, String plaintext) {
+ public Key resolveSigningKey(JwsHeader header, byte[] content) {
return getKey(header.getKeyId());
}
diff --git a/src/main/java/jasper/security/jwt/TokenProviderImpl.java b/src/main/java/jasper/security/jwt/TokenProviderImpl.java
index ca88f234..ce6e0a1e 100644
--- a/src/main/java/jasper/security/jwt/TokenProviderImpl.java
+++ b/src/main/java/jasper/security/jwt/TokenProviderImpl.java
@@ -5,7 +5,6 @@
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
-import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
@@ -68,17 +67,19 @@ public String createToken(Authentication authentication, int validityInSeconds)
var validity = new Date(now + 1000L * validityInSeconds);
return Jwts
.builder()
- .setSubject(authentication.getName())
- .setAudience(security.getClientId())
+ .subject(authentication.getName())
+ .audience()
+ .add(security.getClientId())
+ .and()
.claim(security.getAuthoritiesClaim(), authorities)
.claim(security.getVerifiedEmailClaim(), true)
- .signWith(Keys.hmacShaKeyFor(security.getSecretBytes()), SignatureAlgorithm.HS512)
- .setExpiration(validity)
+ .signWith(Keys.hmacShaKeyFor(security.getSecretBytes()), Jwts.SIG.HS512)
+ .expiration(validity)
.compact();
}
public Authentication getAuthentication(String token, String origin) {
- var claims = getParser(origin).parseClaimsJws(token).getBody();
+ var claims = getParser(origin).parseSignedClaims(token).getPayload();
var principal = getUsername(claims, origin);
var user = getUser(principal);
logger.debug("Token Auth {} {}", principal, origin);
@@ -91,11 +92,11 @@ JwtParser getParser(String origin) {
switch (security.getMode()) {
case "jwt":
var key = Keys.hmacShaKeyFor(security.getSecretBytes());
- jwtParsers.put(origin, Jwts.parserBuilder().setSigningKey(key).build());
+ jwtParsers.put(origin, Jwts.parser().verifyWith(key).build());
break;
case "jwks":
try {
- jwtParsers.put(origin, Jwts.parserBuilder().setSigningKeyResolver(new JwkSigningKeyResolver(new URI(security.getJwksUri()), restTemplate)).build());
+ jwtParsers.put(origin, Jwts.parser().setSigningKeyResolver(new JwkSigningKeyResolver(new URI(security.getJwksUri()), restTemplate)).build());
} catch (URISyntaxException e) {
logger.error("Cannot parse JWKS URI {}", security.getJwksUri());
throw new RuntimeException(e);
@@ -149,7 +150,7 @@ String getUsername(Claims claims, String origin) {
logger.debug("User tag set by JWT claim {}: {} ({})", security.getUsernameClaim(), principal, origin);
}
logger.debug("Principal: {}", principal);
- if (principal.contains("@")) {
+ if (principal != null && principal.contains("@")) {
var emailDomain = principal.substring(principal.indexOf("@") + 1);
principal = principal.substring(0, principal.indexOf("@"));
var security = configs.security(origin);
@@ -192,8 +193,15 @@ public boolean validateToken(String authToken, String origin) {
}
if (!StringUtils.hasText(authToken)) return false;
try {
- var claims = getParser(origin).parseClaimsJws(authToken).getBody();
- if (!security.getClientId().equals(claims.getAudience())) {
+ var claims = getParser(origin).parseSignedClaims(authToken).getPayload();
+ if (isBlank(security.getClientId()) &&
+ claims.getAudience() != null &&
+ (!claims.getAudience().contains("") || !claims.getAudience().isEmpty())) {
+ securityMetersService.trackTokenInvalidAudience();
+ logger.trace(INVALID_JWT_TOKEN + " Invalid Audience");
+ } else if (isNotBlank(security.getClientId()) &&
+ (claims.getAudience() == null || !claims.getAudience().contains(security.getClientId()) || claims.getAudience().size() != 1)) {
+ // TODO: add method to whitelist extra audiences
securityMetersService.trackTokenInvalidAudience();
logger.trace(INVALID_JWT_TOKEN + " Invalid Audience");
} else if (isNotBlank(security.getVerifiedEmailClaim()) && claims.getOrDefault(security.getVerifiedEmailClaim(), Boolean.FALSE).equals(false)) {
@@ -214,6 +222,7 @@ public boolean validateToken(String authToken, String origin) {
} catch (SignatureException e) {
securityMetersService.trackTokenInvalidSignature();
logger.trace(INVALID_JWT_TOKEN, e);
+
} catch (IllegalArgumentException e) {
logger.error("Token validation error {}", e.getMessage());
}
diff --git a/src/test/java/jasper/security/jwt/TokenProviderImplTest.java b/src/test/java/jasper/security/jwt/TokenProviderImplTest.java
index 042401fe..f05407a4 100644
--- a/src/test/java/jasper/security/jwt/TokenProviderImplTest.java
+++ b/src/test/java/jasper/security/jwt/TokenProviderImplTest.java
@@ -57,15 +57,16 @@ TokenProviderImpl getTokenProvider(String localOrigin) {
}
Claims getClaims(String sub) {
- var claims = new DefaultClaims();
- claims.setSubject(sub);
- return claims;
+ return new DefaultClaims(Map.of(
+ "sub", sub
+ ));
}
Claims getClaims(String sub, String auth) {
- var claims = new DefaultClaims(Map.of("auth", auth));
- claims.setSubject(sub);
- return claims;
+ return new DefaultClaims(Map.of(
+ "auth", auth,
+ "sub", sub
+ ));
}
Props getProps(String localOrigin) {
@@ -164,15 +165,15 @@ private String createUnsupportedToken() {
}
private String createTokenWithDifferentSignature() {
- Key otherKey = Keys.hmacShaKeyFor(
+ var otherKey = Keys.hmacShaKeyFor(
Decoders.BASE64.decode("Xfd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")
);
return Jwts
- .builder()
- .setSubject("anonymous")
+ .builder()
+ .subject("anonymous")
.signWith(otherKey, SignatureAlgorithm.HS512)
- .setExpiration(new Date(new Date().getTime() + ONE_MINUTE))
+ .expiration(new Date(new Date().getTime() + ONE_MINUTE))
.compact();
}
diff --git a/src/test/java/jasper/security/jwt/TokenProviderSecurityMetersTests.java b/src/test/java/jasper/security/jwt/TokenProviderSecurityMetersTests.java
index 30af1f5d..3566cffa 100644
--- a/src/test/java/jasper/security/jwt/TokenProviderSecurityMetersTests.java
+++ b/src/test/java/jasper/security/jwt/TokenProviderSecurityMetersTests.java
@@ -155,9 +155,9 @@ private String createTokenWithDifferentSignature() {
return Jwts
.builder()
- .setSubject("anonymous")
+ .subject("anonymous")
.signWith(otherKey, SignatureAlgorithm.HS512)
- .setExpiration(new Date(new Date().getTime() + ONE_MINUTE))
+ .expiration(new Date(new Date().getTime() + ONE_MINUTE))
.compact();
}