Introduce simple refresh strategy

This commit is contained in:
René Pfeuffer
2018-11-30 11:18:37 +01:00
parent 176d121aa0
commit 205ca42e09
3 changed files with 95 additions and 2 deletions

View File

@@ -0,0 +1,25 @@
package sonia.scm.security;
import java.time.Clock;
public class PercentageJwtAccessTokenRefreshStrategy implements JwtAccessTokenRefreshStrategy {
private final Clock clock;
private final float refreshPercentage;
public PercentageJwtAccessTokenRefreshStrategy(float refreshPercentage) {
this(Clock.systemDefaultZone(), refreshPercentage);
}
PercentageJwtAccessTokenRefreshStrategy(Clock clock, float refreshPercentage) {
this.clock = clock;
this.refreshPercentage = refreshPercentage;
}
@Override
public boolean shouldBeRefreshed(JwtAccessToken oldToken) {
long liveSpan = oldToken.getExpiration().getTime() - oldToken.getIssuedAt().getTime();
long age = clock.instant().toEpochMilli() - oldToken.getIssuedAt().getTime();
return age/liveSpan > refreshPercentage;
}
}

View File

@@ -12,12 +12,10 @@ import org.mockito.junit.MockitoJUnitRunner;
import java.sql.Date;
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Optional;
import java.util.Random;
import static java.time.Duration.ofHours;
import static java.time.Duration.ofMinutes;
import static java.time.temporal.ChronoUnit.SECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;

View File

@@ -0,0 +1,70 @@
package sonia.scm.security;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import java.time.Clock;
import java.time.Instant;
import java.util.Collections;
import java.util.Random;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.SECONDS;
import static java.util.concurrent.TimeUnit.HOURS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@SubjectAware(
username = "user",
password = "secret",
configuration = "classpath:sonia/scm/repository/shiro.ini"
)
public class PercentageJwtAccessTokenRefreshStrategyTest {
private static final Instant TOKEN_CREATION = Instant.now().truncatedTo(SECONDS);
@Rule
public ShiroRule shiro = new ShiroRule();
private KeyGenerator keyGenerator = () -> "key";
private Clock refreshClock = mock(Clock.class);
private JwtAccessTokenBuilder tokenBuilder;
private PercentageJwtAccessTokenRefreshStrategy refreshStrategy;
@Before
public void initToken() {
SecureKeyResolver keyResolver = mock(SecureKeyResolver.class);
byte[] bytes = new byte[256];
new Random().nextBytes(bytes);
SecureKey secureKey = new SecureKey(bytes, System.currentTimeMillis());
when(keyResolver.getSecureKey(any())).thenReturn(secureKey);
Clock creationClock = mock(Clock.class);
when(creationClock.instant()).thenReturn(TOKEN_CREATION);
tokenBuilder = new JwtAccessTokenBuilderFactory(keyGenerator, keyResolver, Collections.emptySet(), creationClock).create();
tokenBuilder
.refreshableFor(1, HOURS);
refreshStrategy = new PercentageJwtAccessTokenRefreshStrategy(refreshClock, 0.5F);
}
@Test
public void shouldNotRefreshWhenTokenIsYoung() {
when(refreshClock.instant()).thenReturn(TOKEN_CREATION.plus(1, MINUTES));
assertThat(refreshStrategy.shouldBeRefreshed(tokenBuilder.build())).isFalse();
}
@Test
public void shouldRefreshWhenTokenIsOld() {
when(refreshClock.instant()).thenReturn(TOKEN_CREATION.plus(31, MINUTES));
assertThat(refreshStrategy.shouldBeRefreshed(tokenBuilder.build())).isFalse();
}
}