Skip to content

Commit

Permalink
Update jjwt to 0.12.6 (#102)
Browse files Browse the repository at this point in the history
* Updated jjwt

* Jjwt does not allow a blank string as an audience

Treat empty or missing clientId as requiring an blank or empty aud
Make sure no unrecognized audiences are present

* Fixed tests
  • Loading branch information
cjmalloy authored Jul 16, 2024
1 parent 5febe45 commit 811e155
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 26 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<hibernate-types-55.version>2.21.1</hibernate-types-55.version>
<jsontypedef.version>0.2.2</jsontypedef.version>
<json-patch.version>1.13</json-patch.version>
<jjwt.version>0.11.5</jjwt.version>
<jjwt.version>0.12.5</jjwt.version>
<spring-cloud.version>2021.0.9</spring-cloud.version>
<problem-spring-web.version>0.27.0</problem-spring-web.version>
<springdoc-openapi.version>1.8.0</springdoc-openapi.version>
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/jasper/security/Auth.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -936,7 +937,7 @@ public Claims getClaims() {
if (auth instanceof JwtAuthentication j) {
claims = j.getClaims();
} else {
claims = new DefaultClaims();
claims = claims().build();
}
}
return claims;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down
31 changes: 20 additions & 11 deletions src/main/java/jasper/security/jwt/TokenProviderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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());
}
Expand Down
21 changes: 11 additions & 10 deletions src/test/java/jasper/security/jwt/TokenProviderImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down

0 comments on commit 811e155

Please sign in to comment.