From 37dc8a736507ecbd39eacfd206f8c05aa15e1745 Mon Sep 17 00:00:00 2001 From: Sandor Molnar Date: Tue, 12 Mar 2024 12:20:43 +0100 Subject: [PATCH] KNOX-3018 - Tokens that never expire should not be evicted automatically and their expiration should be displayed properly (#878) --- .../services/token/impl/DefaultTokenStateService.java | 5 +++-- .../gateway/services/token/impl/TokenStateDatabase.java | 4 ++-- .../services/token/impl/JDBCTokenStateServiceTest.java | 8 ++++++-- .../knox/gateway/services/security/token/KnoxToken.java | 2 +- .../token-generation/app/token-generation.service.ts | 2 +- .../token-management/app/token.management.component.ts | 4 ++-- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateService.java b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateService.java index 1676e14fa9..18c7ea24f2 100644 --- a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateService.java +++ b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateService.java @@ -392,9 +392,10 @@ protected Set getExpiredTokens() { * @return true, if the associated token state can be evicted; Otherwise, false. */ protected boolean needsEviction(final String tokenId) throws UnknownTokenException { + final long tokenExpiration = getTokenExpiration(tokenId, false); // If the expiration time(+ grace period) has already passed, it should be considered expired - long expirationWithGrace = getTokenExpiration(tokenId, false) + TimeUnit.SECONDS.toMillis(tokenEvictionGracePeriod); - return (expirationWithGrace <= System.currentTimeMillis()); + long expirationWithGrace = tokenExpiration + TimeUnit.SECONDS.toMillis(tokenEvictionGracePeriod); + return tokenExpiration > 0 && (expirationWithGrace <= System.currentTimeMillis()); } /** diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenStateDatabase.java b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenStateDatabase.java index a461171b4a..b17b7c93bf 100644 --- a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenStateDatabase.java +++ b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenStateDatabase.java @@ -43,8 +43,8 @@ public class TokenStateDatabase { static final String TOKEN_METADATA_TABLE_NAME = "KNOX_TOKEN_METADATA"; private static final String ADD_TOKEN_SQL = "INSERT INTO " + TOKENS_TABLE_NAME + "(token_id, issue_time, expiration, max_lifetime) VALUES(?, ?, ?, ?)"; private static final String REMOVE_TOKEN_SQL = "DELETE FROM " + TOKENS_TABLE_NAME + " WHERE token_id = ?"; - private static final String GET_EXPIRED_TOKENS_SQL = "SELECT token_id FROM " + TOKENS_TABLE_NAME + " WHERE expiration < ?"; - private static final String REMOVE_EXPIRED_TOKENS_SQL = "DELETE FROM " + TOKENS_TABLE_NAME + " WHERE expiration < ?"; + private static final String GET_EXPIRED_TOKENS_SQL = "SELECT token_id FROM " + TOKENS_TABLE_NAME + " WHERE expiration < ? AND expiration > 0"; + private static final String REMOVE_EXPIRED_TOKENS_SQL = "DELETE FROM " + TOKENS_TABLE_NAME + " WHERE expiration < ? AND expiration > 0"; static final String GET_TOKEN_ISSUE_TIME_SQL = "SELECT issue_time FROM " + TOKENS_TABLE_NAME + " WHERE token_id = ?"; static final String GET_TOKEN_EXPIRATION_SQL = "SELECT expiration FROM " + TOKENS_TABLE_NAME + " WHERE token_id = ?"; private static final String UPDATE_TOKEN_EXPIRATION_SQL = "UPDATE " + TOKENS_TABLE_NAME + " SET expiration = ? WHERE token_id = ?"; diff --git a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JDBCTokenStateServiceTest.java b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JDBCTokenStateServiceTest.java index 205c59191a..c30b535453 100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JDBCTokenStateServiceTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JDBCTokenStateServiceTest.java @@ -260,9 +260,13 @@ public void testEvictExpiredTokens() throws Exception { final String tokenId = UUID.randomUUID().toString(); jdbcTokenStateService.addToken(tokenId, 1, 1, 1); } - assertEquals(tokenCount, getLongTokenAttributeFromDatabase(null, GET_TOKENS_COUNT_SQL)); + + //add another token that never expires + jdbcTokenStateService.addToken(UUID.randomUUID().toString(), 1, -1, 1); + + assertEquals(tokenCount + 1, getLongTokenAttributeFromDatabase(null, GET_TOKENS_COUNT_SQL)); jdbcTokenStateService.evictExpiredTokens(); - assertEquals(0, getLongTokenAttributeFromDatabase(null, GET_TOKENS_COUNT_SQL)); + assertEquals(1, getLongTokenAttributeFromDatabase(null, GET_TOKENS_COUNT_SQL)); //the one that never expires should remain } private long getLongTokenAttributeFromDatabase(String tokenId, String sql) throws SQLException { diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/KnoxToken.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/KnoxToken.java index b34397be0e..21359ca883 100644 --- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/KnoxToken.java +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/KnoxToken.java @@ -60,7 +60,7 @@ public long getIssueTimeLong() { } public String getExpiration() { - return KNOX_TOKEN_TS_FORMAT.get().format(new Date(expiration)); + return expiration < 0 ? "Never" : KNOX_TOKEN_TS_FORMAT.get().format(new Date(expiration)); } public long getExpirationLong() { diff --git a/knox-token-generation-ui/token-generation/app/token-generation.service.ts b/knox-token-generation-ui/token-generation/app/token-generation.service.ts index 4c74cab68f..f315988f73 100644 --- a/knox-token-generation-ui/token-generation/app/token-generation.service.ts +++ b/knox-token-generation-ui/token-generation/app/token-generation.service.ts @@ -114,7 +114,7 @@ export class TokenGenService { accessToken: tokenData.access_token, user: jwtJson.sub, accessPasscode: tokenData.passcode, - expiry: new Date(tokenData.expires_in).toLocaleString(), + expiry: tokenData.expires_in < 0 ? 'Never expires' : new Date(tokenData.expires_in).toLocaleString(), homepageURL: this.baseURL + tokenData.homepage_url, targetURL: window.location.protocol + '//' + window.location.host + this.baseURL + tokenData.target_url }; diff --git a/knox-token-management-ui/token-management/app/token.management.component.ts b/knox-token-management-ui/token-management/app/token.management.component.ts index 7ed486c1cc..7d83409cea 100644 --- a/knox-token-management-ui/token-management/app/token.management.component.ts +++ b/knox-token-management-ui/token-management/app/token.management.component.ts @@ -196,11 +196,11 @@ export class TokenManagementComponent implements OnInit { } formatDateTime(dateTime: number) { - return new Date(dateTime).toLocaleString(); + return dateTime < 0 ? 'Never' : new Date(dateTime).toLocaleString(); } isTokenExpired(expiration: number): boolean { - return Date.now() > expiration; + return expiration < 0 ? false : Date.now() > expiration; } getExpirationColor(expiration: number): string {