### Question:
JwtTimestampValidator implements Validator<Token> { @Override public ValidationResult validate(Token token) { ValidationResult validationResult; Instant expiration = token.getExpiration(); if (expiration != null) { validationResult = checkExpiration(expiration); } else { return ValidationResults.createInvalid("Jwt does not contain expiration (exp) claim. Cannot be validated!"); } Instant notBefore = token.getNotBefore(); if (notBefore != null && validationResult.isValid()) { validationResult = checkNotBefore(notBefore); } return validationResult; } JwtTimestampValidator();   JwtTimestampValidator(Supplier<Instant> timeProvider, @Nullable TemporalAmount tolerance); @Override ValidationResult validate(Token token);  }### Answer:
@Test public void token_lacksExpiration_isNotValid() { Token token = tokenFactory.withExpiration(null).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isFalse(); }
@Test public void tokenExpired_beforeClockSkewLeeway_isNotValidAndContainsErrorDescriptionWithDates() { Instant expiration = NOW.minus(ONE_MINUTE); Token token = tokenFactory.withExpiration(expiration).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isFalse(); assertThat(validationResult.getErrorDescription()).contains(NOW.toString()).contains(expiration.toString()); }
@Test public void tokenExpires_afterClockSkewLeeway_isValid() { Token token = tokenFactory.withExpiration(NOW.plus(ONE_MINUTE)).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isTrue(); }
@Test public void tokenExpired_butStillInClockSkewLeeway_isValid() { Token token = tokenFactory.withExpiration(NOW.minus(ONE_MINUTE).plus(ONE_SECOND)).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isTrue(); }
@Test public void tokenLacksNotBefore_isValid() { Token token = tokenFactory.withExpiration(NO_EXPIRE_DATE).withNotBefore(null).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isTrue(); }
@Test public void tokenNotBefore_now_isValid() { Token token = tokenFactory.withExpiration(NO_EXPIRE_DATE).withNotBefore(NOW).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isTrue(); }
@Test public void tokenNotBefore_insideClockSkewLeeway_isValid() { Token token = tokenFactory .withExpiration(NO_EXPIRE_DATE) .withNotBefore(NOW.plus(ONE_MINUTE).minus(ONE_SECOND)) .build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isValid()).isTrue(); }
@Test public void tokenNotBefore_afterClockSkewLeeway_isNotValidAndContainsErrorDescription() { Instant inOneMinute = NOW.plus(ONE_MINUTE); Token token = tokenFactory.withExpiration(NO_EXPIRE_DATE).withNotBefore(inOneMinute).build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isErroneous()).isTrue(); assertThat(validationResult.getErrorDescription()).contains(NOW.toString()).contains(inOneMinute.toString()); }
@Test public void tokenNotBeforeIsValidButIsAlreadyExpired_isNotValid() { Token token = tokenFactory .withExpiration(NOW.minus(Duration.ofMinutes(2))) .withNotBefore(NOW) .build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isErroneous()).isTrue(); }
@Test public void tokenNotExpiredButNotBeforeNotReachedYet_isNotValid() { Instant inTwoMinutes = NOW.plus(Duration.ofMinutes(2)); Token token = tokenFactory .withExpiration(inTwoMinutes) .withNotBefore(inTwoMinutes) .build(); ValidationResult validationResult = cut.validate(token); assertThat(validationResult.isErroneous()).isTrue(); }