Repository: syncope Updated Branches: refs/heads/master b41675a33 -> 2b4053df1
SYNCOPE-1179 - JWT "Date" claims are interpreted using milliseconds instead of seconds Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/2b4053df Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/2b4053df Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/2b4053df Branch: refs/heads/master Commit: 2b4053df14d74e47c55ced76b713fc1baba0abda Parents: b41675a Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Fri Jul 28 14:50:03 2017 +0100 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Fri Jul 28 14:50:03 2017 +0100 ---------------------------------------------------------------------- .../java/data/AccessTokenDataBinderImpl.java | 24 ++++---- .../security/JWTAuthenticationProvider.java | 4 +- .../org/apache/syncope/fit/core/JWTITCase.java | 58 +++++++++++--------- 3 files changed, 48 insertions(+), 38 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/2b4053df/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java index f30562d..d886db6 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java @@ -87,16 +87,16 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { credentialChecker.checkIsDefaultJWSKeyInUse(); - Date now = new Date(); - Date expiry = new Date(now.getTime() + 60L * 1000L * duration); + long currentTime = new Date().getTime() / 1000L; + long expiryTime = currentTime + 60L * duration; JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(UUID_GENERATOR.generate().toString()); jwtClaims.setSubject(subject); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(jwtIssuer); - jwtClaims.setExpiryTime(expiry.getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiryTime); + jwtClaims.setNotBefore(currentTime); for (Map.Entry<String, Object> entry : claims.entrySet()) { jwtClaims.setClaim(entry.getKey(), entry.getValue()); } @@ -107,7 +107,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { String signed = producer.signWith(jwsSignatureProvider); - return Triple.of(jwtClaims.getTokenId(), signed, expiry); + return Triple.of(jwtClaims.getTokenId(), signed, new Date(expiryTime * 1000L)); } @Override @@ -164,10 +164,11 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { credentialChecker.checkIsDefaultJWSKeyInUse(); - Date now = new Date(); long duration = confDAO.find("jwt.lifetime.minutes", 120L); - Date expiry = new Date(now.getTime() + 60L * 1000L * duration); - consumer.getJwtClaims().setExpiryTime(expiry.getTime()); + long currentTime = new Date().getTime() / 1000L; + long expiry = currentTime + 60L * duration; + consumer.getJwtClaims().setExpiryTime(expiry); + Date expiryDate = new Date(expiry * 1000L); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, jwsSignatureProvider.getAlgorithm()); JwtToken token = new JwtToken(jwsHeaders, consumer.getJwtClaims()); @@ -176,7 +177,8 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { String body = producer.signWith(jwsSignatureProvider); accessToken.setBody(body); - accessToken.setExpiryTime(expiry); + // AccessToken stores expiry time in milliseconds, as opposed to seconds for the JWT tokens. + accessToken.setExpiryTime(expiryDate); if (!adminUser.equals(accessToken.getOwner())) { try { @@ -190,7 +192,7 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { accessTokenDAO.save(accessToken); - return Pair.of(body, expiry); + return Pair.of(body, expiryDate); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/2b4053df/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java index 36d718a..2741d86 100644 --- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java +++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationProvider.java @@ -57,13 +57,13 @@ public class JWTAuthenticationProvider implements AuthenticationProvider { Long referenceTime = new Date().getTime(); Long expiryTime = claims.getExpiryTime(); - if (expiryTime == null || expiryTime < referenceTime) { + if (expiryTime == null || (expiryTime * 1000L) < referenceTime) { dataAccessor.removeExpired(claims.getTokenId()); throw new CredentialsExpiredException("JWT is expired"); } Long notBefore = claims.getNotBefore(); - if (notBefore == null || notBefore > referenceTime) { + if (notBefore == null || (notBefore * 1000L) > referenceTime) { throw new CredentialsExpiredException("JWT not valid yet"); } http://git-wip-us.apache.org/repos/asf/syncope/blob/2b4053df/fit/core-reference/src/test/java/org/apache/syncope/fit/core/JWTITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/JWTITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/JWTITCase.java index 5beb9b6..93ae426 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/JWTITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/JWTITCase.java @@ -86,7 +86,7 @@ public class JWTITCase extends AbstractITCase { assertNotNull(expiryTime); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); - Date tokenDate = dateFormat.parse(dateFormat.format(new Date(expiryTime))); + Date tokenDate = dateFormat.parse(dateFormat.format(new Date(expiryTime * 1000L))); Date parsedDate = dateFormat.parse(expiry); assertEquals(tokenDate, parsedDate); @@ -147,6 +147,7 @@ public class JWTITCase extends AbstractITCase { // Create a new token using the Id of the first token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -155,10 +156,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(tokenId); jwtClaims.setSubject(ADMIN_UNAME); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(JWT_ISSUER); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -187,6 +188,7 @@ public class JWTITCase extends AbstractITCase { // Create a new token using the Id of the first token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -195,10 +197,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(tokenId); jwtClaims.setSubject(ADMIN_UNAME); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer("UnknownIssuer"); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -232,6 +234,7 @@ public class JWTITCase extends AbstractITCase { // Create a new token using the Id of the first token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -240,10 +243,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(tokenId); jwtClaims.setSubject(ADMIN_UNAME); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(JWT_ISSUER); - jwtClaims.setExpiryTime(now.getTime() - 5000L); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime((now.getTime() - 5000L) / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -277,6 +280,7 @@ public class JWTITCase extends AbstractITCase { // Create a new token using the Id of the first token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -285,10 +289,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(tokenId); jwtClaims.setSubject(ADMIN_UNAME); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(JWT_ISSUER); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime() + 60000L); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime + 60L); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -358,6 +362,7 @@ public class JWTITCase extends AbstractITCase { // Create a new token using an unknown Id Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -366,10 +371,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(UUID.randomUUID().toString()); jwtClaims.setSubject(ADMIN_UNAME); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(JWT_ISSUER); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -393,6 +398,7 @@ public class JWTITCase extends AbstractITCase { public void thirdPartyToken() throws ParseException { // Create a new token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -401,10 +407,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(UUID.randomUUID().toString()); jwtClaims.setSubject("pucc...@apache.org"); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(CustomJWTSSOProvider.ISSUER); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -425,6 +431,7 @@ public class JWTITCase extends AbstractITCase { public void thirdPartyTokenUnknownUser() throws ParseException { // Create a new token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -433,10 +440,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(UUID.randomUUID().toString()); jwtClaims.setSubject("stra...@apache.org"); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(CustomJWTSSOProvider.ISSUER); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims); @@ -460,6 +467,7 @@ public class JWTITCase extends AbstractITCase { public void thirdPartyTokenUnknownIssuer() throws ParseException { // Create a new token Date now = new Date(); + long currentTime = now.getTime() / 1000L; Calendar expiry = Calendar.getInstance(); expiry.setTime(now); @@ -468,10 +476,10 @@ public class JWTITCase extends AbstractITCase { JwtClaims jwtClaims = new JwtClaims(); jwtClaims.setTokenId(UUID.randomUUID().toString()); jwtClaims.setSubject("pucc...@apache.org"); - jwtClaims.setIssuedAt(now.getTime()); + jwtClaims.setIssuedAt(currentTime); jwtClaims.setIssuer(CustomJWTSSOProvider.ISSUER + "_"); - jwtClaims.setExpiryTime(expiry.getTime().getTime()); - jwtClaims.setNotBefore(now.getTime()); + jwtClaims.setExpiryTime(expiry.getTime().getTime() / 1000L); + jwtClaims.setNotBefore(currentTime); JwsHeaders jwsHeaders = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); JwtToken jwtToken = new JwtToken(jwsHeaders, jwtClaims);