/** * {@inheritDoc} */ @Override public Map<String, Object> convert(Map<String, Object> claims) { Assert.notNull(claims, "claims cannot be null"); Map<String, Object> mappedClaims = new HashMap<>(claims); for (Map.Entry<String, Converter<Object, ?>> entry : this.claimConverters.entrySet()) { String claimName = entry.getKey(); Converter<Object, ?> converter = entry.getValue(); if (converter != null) { Object claim = claims.get(claimName); Object mappedClaim = converter.convert(claim); mappedClaims.compute(claimName, (key, value) -> mappedClaim); } } Instant issuedAt = (Instant) mappedClaims.get(JwtClaimNames.IAT); Instant expiresAt = (Instant) mappedClaims.get(JwtClaimNames.EXP); if (issuedAt == null && expiresAt != null) { mappedClaims.put(JwtClaimNames.IAT, expiresAt.minusSeconds(1)); } return mappedClaims; }
@Test public void convertWhenUsingDefaultsThenBasesIssuedAtOffOfExpiration() { MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); Map<String, Object> source = Collections.singletonMap(JwtClaimNames.EXP, 1000000000L); Map<String, Object> target = converter.convert(source); assertThat(target.get(JwtClaimNames.EXP)).isEqualTo(Instant.ofEpochSecond(1000000000L)); assertThat(target.get(JwtClaimNames.IAT)).isEqualTo(Instant.ofEpochSecond(1000000000L).minusSeconds(1)); }
@Test public void convertWhenUsingCustomExpiresAtConverterThenIssuedAtConverterStillConsultsIt() { Instant at = Instant.ofEpochMilli(1000000000000L); Converter<Object, Instant> expiresAtConverter = mock(Converter.class); when(expiresAtConverter.convert(any())).thenReturn(at); MappedJwtClaimSetConverter converter = MappedJwtClaimSetConverter .withDefaults(Collections.singletonMap(JwtClaimNames.EXP, expiresAtConverter)); Map<String, Object> source = new HashMap<>(); Map<String, Object> target = converter.convert(source); assertThat(target.get(JwtClaimNames.IAT)). isEqualTo(Instant.ofEpochMilli(at.toEpochMilli()).minusSeconds(1)); }
@Test public void getClaimAsInstantWhenDoubleTypeSecondsThenReturnInstant() { Instant expectedClaimValue = Instant.now(); String claimName = "doubleSeconds"; this.claims.put(claimName, Long.valueOf(expectedClaimValue.getEpochSecond()).doubleValue()); assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); }
@Test public void getClaimAsInstantWhenIntegerTypeSecondsThenReturnInstant() { Instant expectedClaimValue = Instant.now(); String claimName = "integerSeconds"; this.claims.put(claimName, Long.valueOf(expectedClaimValue.getEpochSecond()).intValue()); assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); }
@Test public void handleReturnValueLastModified() throws Exception { Instant currentTime = Instant.now().truncatedTo(ChronoUnit.SECONDS); Instant oneMinAgo = currentTime.minusSeconds(60); long timestamp = currentTime.toEpochMilli(); MockServerWebExchange exchange = MockServerWebExchange.from(get("/path").ifModifiedSince(timestamp)); ResponseEntity<String> entity = ok().lastModified(oneMinAgo.toEpochMilli()).body("body"); MethodParameter returnType = on(TestController.class).resolveReturnType(entity(String.class)); HandlerResult result = handlerResult(entity, returnType); this.resultHandler.handleResult(exchange, result).block(Duration.ofSeconds(5)); assertConditionalResponse(exchange, HttpStatus.NOT_MODIFIED, null, null, oneMinAgo); }
@Test public void getClaimAsInstantWhenDateTypeThenReturnInstant() { Instant expectedClaimValue = Instant.now(); String claimName = "date"; this.claims.put(claimName, Date.from(expectedClaimValue)); assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); }
@Test public void getClaimAsInstantWhenLongTypeSecondsThenReturnInstant() { Instant expectedClaimValue = Instant.now(); String claimName = "longSeconds"; this.claims.put(claimName, expectedClaimValue.getEpochSecond()); assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); }
@Test public void getClaimAsInstantWhenInstantTypeThenReturnInstant() { Instant expectedClaimValue = Instant.now(); String claimName = "instant"; this.claims.put(claimName, expectedClaimValue); assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); }
@Test public void validateWhenJwtIsExpiredThenErrorMessageIndicatesExpirationTime() { Instant oneHourAgo = Instant.now().minusSeconds(3600); Jwt jwt = new Jwt( MOCK_TOKEN_VALUE, MOCK_ISSUED_AT, oneHourAgo, MOCK_HEADER, MOCK_CLAIM_SET); JwtTimestampValidator jwtValidator = new JwtTimestampValidator(); Collection<OAuth2Error> details = jwtValidator.validate(jwt).getErrors(); Collection<String> messages = details.stream().map(OAuth2Error::getDescription).collect(Collectors.toList()); assertThat(messages).contains("Jwt expired at " + oneHourAgo); }
@Test public void handleReturnValueETagAndLastModified() throws Exception { String eTag = "\"deadb33f8badf00d\""; Instant currentTime = Instant.now().truncatedTo(ChronoUnit.SECONDS); Instant oneMinAgo = currentTime.minusSeconds(60); MockServerWebExchange exchange = MockServerWebExchange.from(get("/path") .ifNoneMatch(eTag) .ifModifiedSince(currentTime.toEpochMilli()) ); ResponseEntity<String> entity = ok().eTag(eTag).lastModified(oneMinAgo.toEpochMilli()).body("body"); MethodParameter returnType = on(TestController.class).resolveReturnType(entity(String.class)); HandlerResult result = handlerResult(entity, returnType); this.resultHandler.handleResult(exchange, result).block(Duration.ofSeconds(5)); assertConditionalResponse(exchange, HttpStatus.NOT_MODIFIED, null, eTag, oneMinAgo); }
@Test public void handleReturnValueChangedETagAndLastModified() throws Exception { String etag = "\"deadb33f8badf00d\""; String newEtag = "\"changed-etag-value\""; Instant currentTime = Instant.now().truncatedTo(ChronoUnit.SECONDS); Instant oneMinAgo = currentTime.minusSeconds(60); MockServerWebExchange exchange = MockServerWebExchange.from(get("/path") .ifNoneMatch(etag) .ifModifiedSince(currentTime.toEpochMilli()) ); ResponseEntity<String> entity = ok().eTag(newEtag).lastModified(oneMinAgo.toEpochMilli()).body("body"); MethodParameter returnType = on(TestController.class).resolveReturnType(entity(String.class)); HandlerResult result = handlerResult(entity, returnType); this.resultHandler.handleResult(exchange, result).block(Duration.ofSeconds(5)); assertConditionalResponse(exchange, HttpStatus.OK, "body", newEtag, oneMinAgo); }
@Test(expected = IllegalArgumentException.class) public void constructorWhenExpiresAtBeforeIssuedAtThenThrowIllegalArgumentException() { new OAuth2AccessToken(TOKEN_TYPE, TOKEN_VALUE, ISSUED_AT, Instant.from(ISSUED_AT).minusSeconds(1)); }
@Test public void getSessionExpired() { verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); MapSession expired = new MapSession(); expired.setLastAccessedTime(Instant.now() .minusSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1)); given(this.sessions.get(eq(expired.getId()))).willReturn(expired); HazelcastSession session = this.repository.findById(expired.getId()); assertThat(session).isNull(); verify(this.sessions, times(1)).get(eq(expired.getId())); verify(this.sessions, times(1)).remove(eq(expired.getId())); verifyZeroInteractions(this.sessions); }
Instant almostOneDayFromNow = now.plus(oneDayOff).minusSeconds(10); Instant justOverOneDayAgo = now.minus(oneDayOff).minusSeconds(10); Instant justOverOneDayFromNow = now.plus(oneDayOff).plusSeconds(10);
@Test public void checkModifiedTimestamp() { Instant oneMinuteAgo = currentDate.minusSeconds(60); MockServerHttpRequest request = get("/").ifModifiedSince(oneMinuteAgo.toEpochMilli()).build(); MockServerWebExchange exchange = MockServerWebExchange.from(request); assertFalse(exchange.checkNotModified(currentDate)); assertNull(exchange.getResponse().getStatusCode()); assertEquals(currentDate.toEpochMilli(), exchange.getResponse().getHeaders().getLastModified()); }
@Test public void checkNotModifiedTimestampConditionalPutConflict() throws Exception { Instant oneMinuteAgo = currentDate.minusSeconds(60); long millis = oneMinuteAgo.toEpochMilli(); MockServerHttpRequest request = MockServerHttpRequest.put("/").ifUnmodifiedSince(millis).build(); MockServerWebExchange exchange = MockServerWebExchange.from(request); assertTrue(exchange.checkNotModified(currentDate)); assertEquals(412, exchange.getResponse().getStatusCode().value()); assertEquals(-1, exchange.getResponse().getHeaders().getLastModified()); }
@Test public void checkNotModifiedETagAndModifiedTimestamp() { String eTag = "\"Foo\""; Instant oneMinuteAgo = currentDate.minusSeconds(60); MockServerWebExchange exchange = MockServerWebExchange.from(get("/") .ifNoneMatch(eTag) .ifModifiedSince(oneMinuteAgo.toEpochMilli()) ); assertTrue(exchange.checkNotModified(eTag, currentDate)); assertEquals(304, exchange.getResponse().getStatusCode().value()); assertEquals(eTag, exchange.getResponse().getHeaders().getETag()); assertEquals(currentDate.toEpochMilli(), exchange.getResponse().getHeaders().getLastModified()); }
@Test public void checkNotModifiedTimestampConditionalPut() throws Exception { Instant oneMinuteAgo = currentDate.minusSeconds(60); long millis = currentDate.toEpochMilli(); MockServerHttpRequest request = MockServerHttpRequest.put("/").ifUnmodifiedSince(millis).build(); MockServerWebExchange exchange = MockServerWebExchange.from(request); assertFalse(exchange.checkNotModified(oneMinuteAgo)); assertNull(exchange.getResponse().getStatusCode()); assertEquals(-1, exchange.getResponse().getHeaders().getLastModified()); }
@Test @SuppressWarnings("unchecked") public void getSessionExpired() { Session expired = this.repository.new JdbcSession(); expired.setLastAccessedTime(Instant.now().minusSeconds( MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1)); given(this.jdbcOperations.query(isA(String.class), isA(PreparedStatementSetter.class), isA(ResultSetExtractor.class))) .willReturn(Collections.singletonList(expired)); JdbcOperationsSessionRepository.JdbcSession session = this.repository .findById(expired.getId()); assertThat(session).isNull(); assertPropagationRequiresNew(); verify(this.jdbcOperations, times(1)).query(isA(String.class), isA(PreparedStatementSetter.class), isA(ResultSetExtractor.class)); verify(this.jdbcOperations, times(1)).update(startsWith("DELETE"), eq(expired.getId())); }