From e8672bbeff45f7054defbfc4b1c494714e01f311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 30 Nov 2018 10:15:12 +0100 Subject: [PATCH] Keep refresh expiration --- .../main/java/sonia/scm/security/JwtAccessToken.java | 2 +- .../sonia/scm/security/JwtAccessTokenBuilder.java | 9 +++++++++ .../sonia/scm/security/JwtAccessTokenRefresher.java | 3 ++- .../scm/security/JwtAccessTokenRefresherTest.java | 12 ++++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java index 7832a463a3..8fb5929188 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java +++ b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java @@ -47,7 +47,7 @@ import static java.util.Optional.ofNullable; */ public final class JwtAccessToken implements AccessToken { - public static final String REFRESHABLE_UNTIL_CLAIM_KEY = "scm-manager.refreshableUntil"; + public static final String REFRESHABLE_UNTIL_CLAIM_KEY = "scm-manager.refreshExpiration"; public static final String PARENT_TOKEN_ID_CLAIM_KEY = "scm-manager.parentTokenId"; private final Claims claims; private final String compact; diff --git a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java index a261c9a303..66db720125 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java +++ b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java @@ -71,6 +71,7 @@ public final class JwtAccessTokenBuilder implements AccessTokenBuilder { private TimeUnit expiresInUnit = TimeUnit.HOURS; private long refreshableFor = 12; private TimeUnit refreshableForUnit = TimeUnit.HOURS; + private Instant refreshExpiration; private String parentKeyId; private Scope scope = Scope.empty(); @@ -133,6 +134,12 @@ public final class JwtAccessTokenBuilder implements AccessTokenBuilder { return this; } + JwtAccessTokenBuilder refreshExpiration(Instant refreshExpiration) { + this.refreshExpiration = refreshExpiration; + this.refreshableFor = 0; + return this; + } + public JwtAccessTokenBuilder parentKey(String parentKeyId) { this.parentKeyId = parentKeyId; return this; @@ -175,6 +182,8 @@ public final class JwtAccessTokenBuilder implements AccessTokenBuilder { if (refreshableFor > 0) { long refreshExpiration = refreshableForUnit.toMillis(refreshableFor); claims.put(JwtAccessToken.REFRESHABLE_UNTIL_CLAIM_KEY, new Date(now.toEpochMilli() + refreshExpiration).getTime()); + } else if (refreshExpiration != null) { + claims.put(JwtAccessToken.REFRESHABLE_UNTIL_CLAIM_KEY, Date.from(refreshExpiration)); } if (parentKeyId == null) { claims.put(JwtAccessToken.PARENT_TOKEN_ID_CLAIM_KEY, id); diff --git a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenRefresher.java b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenRefresher.java index f219262626..5efc01a096 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenRefresher.java +++ b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenRefresher.java @@ -29,7 +29,7 @@ public class JwtAccessTokenRefresher { this.clock = clock; } - public Optional refresh(JwtAccessToken oldToken) { + Optional refresh(JwtAccessToken oldToken) { JwtAccessTokenBuilder builder = builderFactory.create(); Map claims = oldToken.getClaims(); claims.forEach(builder::custom); @@ -42,6 +42,7 @@ public class JwtAccessTokenRefresher { } builder.expiresIn(computeOldExpirationInMillis(oldToken), TimeUnit.MILLISECONDS); builder.parentKey(parentTokenId.get().toString()); + builder.refreshExpiration(oldToken.getRefreshExpiration().get().toInstant()); return Optional.of(builder.build()); } else { return Optional.empty(); diff --git a/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenRefresherTest.java b/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenRefresherTest.java index 92c6bb98e9..83f528092c 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenRefresherTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenRefresherTest.java @@ -142,4 +142,16 @@ public class JwtAccessTokenRefresherTest { JwtAccessToken refreshedToken = refreshedTokenResult.get(); assertThat(refreshedToken.getExpiration()).isEqualTo(Date.from(NOW.plus(ofMinutes(5)))); } + + @Test + public void shouldRefreshTokenWithSameRefreshExpiration() { + JwtAccessToken oldToken = tokenBuilder.build(); + when(refreshStrategy.shouldBeRefreshed(oldToken)).thenReturn(true); + + Optional refreshedTokenResult = refresher.refresh(oldToken); + + assertThat(refreshedTokenResult).isNotEmpty(); + JwtAccessToken refreshedToken = refreshedTokenResult.get(); + assertThat(refreshedToken.getRefreshExpiration()).get().isEqualTo(Date.from(TOKEN_CREATION.plus(ofMinutes(10)))); + } }