diff --git a/src/main/java/net/snowflake/client/core/FileCacheManager.java b/src/main/java/net/snowflake/client/core/FileCacheManager.java index 2d00d6d0a..80ac82754 100644 --- a/src/main/java/net/snowflake/client/core/FileCacheManager.java +++ b/src/main/java/net/snowflake/client/core/FileCacheManager.java @@ -27,6 +27,7 @@ import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.Date; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import net.snowflake.client.log.SFLogger; @@ -43,7 +44,6 @@ class FileCacheManager { private String cacheDirectorySystemProperty; private String cacheDirectoryEnvironmentVariable; private String baseCacheFileName; - private long cacheExpirationInMilliseconds; private long cacheFileLockExpirationInMilliseconds; private File cacheFile; @@ -74,12 +74,6 @@ FileCacheManager setBaseCacheFileName(String baseCacheFileName) { return this; } - FileCacheManager setCacheExpirationInSeconds(long cacheExpirationInSeconds) { - // converting from seconds to milliseconds - this.cacheExpirationInMilliseconds = cacheExpirationInSeconds * 1000; - return this; - } - FileCacheManager setCacheFileLockExpirationInSeconds(long cacheFileLockExpirationInSeconds) { this.cacheFileLockExpirationInMilliseconds = cacheFileLockExpirationInSeconds * 1000; return this; @@ -90,6 +84,10 @@ FileCacheManager setOnlyOwnerPermissions(boolean onlyOwnerPermissions) { return this; } + String getCacheFilePath() { + return cacheFile.getAbsolutePath(); + } + /** * Override the cache file. * @@ -100,7 +98,7 @@ void overrideCacheFile(File newCacheFile) { logger.debug("Cache file doesn't exists. File: {}", newCacheFile); } if (onlyOwnerPermissions) { - FileUtil.throwWhenPermiossionDifferentThanReadWriteForOwner( + FileUtil.throwWhenPermissionsDifferentThanReadWriteForOwner( newCacheFile, "Override cache file"); } else { FileUtil.logFileUsage(cacheFile, "Override cache file", false); @@ -199,12 +197,33 @@ FileCacheManager build() { return this; } - /** Reads the cache file. */ - JsonNode readCacheFile() { - if (cacheFile == null || !this.checkCacheLockFile()) { - // no cache or the cache is not valid. + T withLock(Supplier supplier) { + if (cacheFile == null) { + logger.error("No cache file assigned", false); + return null; + } + if (cacheLockFile == null) { + logger.error("No cache lock file assigned", false); return null; + } else if (cacheLockFile.exists()) { + deleteCacheLockIfExpired(); + } + + if (!tryToLockCacheFile()) { + logger.debug("Failed to lock the file. Skipping cache operation", false); + return null; + } + try { + return supplier.get(); + } finally { + if (!unlockCacheFile()) { + logger.debug("Failed to unlock cache file", false); + } } + } + + /** Reads the cache file. */ + JsonNode readCacheFile() { try { if (!cacheFile.exists()) { logger.debug("Cache file doesn't exists. File: {}", cacheFile); @@ -215,7 +234,7 @@ JsonNode readCacheFile() { new InputStreamReader(new FileInputStream(cacheFile), DEFAULT_FILE_ENCODING)) { if (onlyOwnerPermissions) { - FileUtil.throwWhenPermiossionDifferentThanReadWriteForOwner(cacheFile, "Read cache"); + FileUtil.throwWhenPermissionsDifferentThanReadWriteForOwner(cacheFile, "Read cache"); FileUtil.throwWhenOwnerDifferentThanCurrentUser(cacheFile, "Read cache"); } else { FileUtil.logFileUsage(cacheFile, "Read cache", false); @@ -230,13 +249,6 @@ JsonNode readCacheFile() { void writeCacheFile(JsonNode input) { logger.debug("Writing cache file. File: {}", cacheFile); - if (cacheFile == null || !tryLockCacheFile()) { - // no cache file or it failed to lock file - logger.debug( - "No cache file exists or failed to lock the file. Skipping writing the cache", false); - return; - } - // NOTE: must unlock cache file try { if (input == null) { return; @@ -244,7 +256,7 @@ void writeCacheFile(JsonNode input) { try (Writer writer = new OutputStreamWriter(new FileOutputStream(cacheFile), DEFAULT_FILE_ENCODING)) { if (onlyOwnerPermissions) { - FileUtil.throwWhenPermiossionDifferentThanReadWriteForOwner(cacheFile, "Write to cache"); + FileUtil.throwWhenPermissionsDifferentThanReadWriteForOwner(cacheFile, "Write to cache"); } else { FileUtil.logFileUsage(cacheFile, "Write to cache", false); } @@ -252,10 +264,6 @@ void writeCacheFile(JsonNode input) { } } catch (IOException ex) { logger.debug("Failed to write the cache file. File: {}", cacheFile); - } finally { - if (!unlockCacheFile()) { - logger.debug("Failed to unlock cache file", false); - } } } @@ -277,10 +285,10 @@ void deleteCacheFile() { * * @return true if success or false */ - private boolean tryLockCacheFile() { + private boolean tryToLockCacheFile() { int cnt = 0; boolean locked = false; - while (cnt < 100 && !(locked = lockCacheFile())) { + while (cnt < 10 && !(locked = lockCacheFile())) { try { Thread.sleep(100); } catch (InterruptedException ex) { @@ -289,56 +297,27 @@ private boolean tryLockCacheFile() { ++cnt; } if (!locked) { - logger.debug("Failed to lock the cache file.", false); + deleteCacheLockIfExpired(); + if (!lockCacheFile()) { + logger.debug("Failed to lock the cache file.", false); + } } return locked; } - /** - * Lock cache file by creating a lock directory - * - * @return true if success or false - */ - private boolean lockCacheFile() { - return cacheLockFile.mkdirs(); - } - - /** - * Unlock cache file by deleting a lock directory - * - * @return true if success or false - */ - private boolean unlockCacheFile() { - return cacheLockFile.delete(); - } - - private boolean checkCacheLockFile() { + private void deleteCacheLockIfExpired() { long currentTime = new Date().getTime(); - long cacheFileTs = fileCreationTime(cacheFile); - - if (!cacheLockFile.exists() - && cacheFileTs > 0 - && currentTime - this.cacheExpirationInMilliseconds <= cacheFileTs) { - logger.debug("No cache file lock directory exists and cache file is up to date.", false); - return true; - } - long lockFileTs = fileCreationTime(cacheLockFile); if (lockFileTs < 0) { - // failed to get the timestamp of lock directory - return false; + logger.debug("Failed to get the timestamp of lock directory"); } if (lockFileTs < currentTime - this.cacheFileLockExpirationInMilliseconds) { // old lock file if (!cacheLockFile.delete()) { logger.debug("Failed to delete the directory. Dir: {}", cacheLockFile); - return false; } - logger.debug("Deleted the cache lock directory, because it was old.", false); - return currentTime - this.cacheExpirationInMilliseconds <= cacheFileTs; + logger.debug("Deleted expired cache lock directory.", false); } - logger.debug("Failed to lock the file. Ignored.", false); - return false; } /** @@ -361,7 +340,21 @@ private static long fileCreationTime(File targetFile) { return -1; } - String getCacheFilePath() { - return cacheFile.getAbsolutePath(); + /** + * Lock cache file by creating a lock directory + * + * @return true if success or false + */ + private boolean lockCacheFile() { + return cacheLockFile.mkdirs(); + } + + /** + * Unlock cache file by deleting a lock directory + * + * @return true if success or false + */ + private boolean unlockCacheFile() { + return cacheLockFile.delete(); } } diff --git a/src/main/java/net/snowflake/client/core/FileUtil.java b/src/main/java/net/snowflake/client/core/FileUtil.java index 005b9ac18..5acb38b9b 100644 --- a/src/main/java/net/snowflake/client/core/FileUtil.java +++ b/src/main/java/net/snowflake/client/core/FileUtil.java @@ -41,11 +41,11 @@ public static void logFileUsage(String stringPath, String context, boolean logRe logFileUsage(path, context, logReadAccess); } - public static void throwWhenPermiossionDifferentThanReadWriteForOwner(File file, String context) { - throwWhenPermiossionDifferentThanReadWriteForOwner(file.toPath(), context); + public static void throwWhenPermissionsDifferentThanReadWriteForOwner(File file, String context) { + throwWhenPermissionsDifferentThanReadWriteForOwner(file.toPath(), context); } - public static void throwWhenPermiossionDifferentThanReadWriteForOwner( + public static void throwWhenPermissionsDifferentThanReadWriteForOwner( Path filePath, String context) { // we do not check the permissions for Windows if (isWindows()) { @@ -62,7 +62,9 @@ public static void throwWhenPermiossionDifferentThanReadWriteForOwner( logger.debug( "{}File {} access rights: {}", getContextStr(context), filePath, filePermissions); throw new SecurityException( - String.format("Access to file %s is wider than allowed only to the owner", filePath)); + String.format( + "Access to file %s is wider than allowed only to the owner. Remove cached files and re-run the driver.", + filePath)); } } catch (IOException e) { throw new SecurityException( diff --git a/src/main/java/net/snowflake/client/core/SFTrustManager.java b/src/main/java/net/snowflake/client/core/SFTrustManager.java index 6440ec6c3..f0ce0c53b 100644 --- a/src/main/java/net/snowflake/client/core/SFTrustManager.java +++ b/src/main/java/net/snowflake/client/core/SFTrustManager.java @@ -225,7 +225,6 @@ public class SFTrustManager extends X509ExtendedTrustManager { .setCacheDirectorySystemProperty(CACHE_DIR_PROP) .setCacheDirectoryEnvironmentVariable(CACHE_DIR_ENV) .setBaseCacheFileName(CACHE_FILE_NAME) - .setCacheExpirationInSeconds(CACHE_EXPIRATION_IN_SECONDS) .setCacheFileLockExpirationInSeconds(CACHE_FILE_LOCK_EXPIRATION_IN_SECONDS) .setOnlyOwnerPermissions(false) .build(); @@ -544,7 +543,7 @@ private static void verifySignature( * @param bytes a byte array * @return a string in hexadecimal code */ - private static String byteToHexString(byte[] bytes) { + static String byteToHexString(byte[] bytes) { final char[] hexArray = "0123456789ABCDEF".toCharArray(); char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { diff --git a/src/main/java/net/snowflake/client/core/SecureStorageAppleManager.java b/src/main/java/net/snowflake/client/core/SecureStorageAppleManager.java index fb467edcc..bfe7540bf 100644 --- a/src/main/java/net/snowflake/client/core/SecureStorageAppleManager.java +++ b/src/main/java/net/snowflake/client/core/SecureStorageAppleManager.java @@ -32,7 +32,7 @@ public SecureStorageStatus setCredential(String host, String user, String type, return SecureStorageStatus.SUCCESS; } - String target = SecureStorageManager.convertTarget(host, user, type); + String target = SecureStorageManager.buildCredentialsKey(host, user, type); byte[] targetBytes = target.getBytes(StandardCharsets.UTF_8); byte[] userBytes = user.toUpperCase().getBytes(StandardCharsets.UTF_8); byte[] credBytes = cred.getBytes(StandardCharsets.UTF_8); @@ -92,7 +92,7 @@ public SecureStorageStatus setCredential(String host, String user, String type, } public String getCredential(String host, String user, String type) { - String target = SecureStorageManager.convertTarget(host, user, type); + String target = SecureStorageManager.buildCredentialsKey(host, user, type); byte[] targetBytes = target.getBytes(StandardCharsets.UTF_8); byte[] userBytes = user.toUpperCase().getBytes(StandardCharsets.UTF_8); @@ -141,7 +141,7 @@ public String getCredential(String host, String user, String type) { } public SecureStorageStatus deleteCredential(String host, String user, String type) { - String target = SecureStorageManager.convertTarget(host, user, type); + String target = SecureStorageManager.buildCredentialsKey(host, user, type); byte[] targetBytes = target.getBytes(StandardCharsets.UTF_8); byte[] userBytes = user.toUpperCase().getBytes(StandardCharsets.UTF_8); diff --git a/src/main/java/net/snowflake/client/core/SecureStorageLinuxManager.java b/src/main/java/net/snowflake/client/core/SecureStorageLinuxManager.java index d8c44dda3..fda5f20d6 100644 --- a/src/main/java/net/snowflake/client/core/SecureStorageLinuxManager.java +++ b/src/main/java/net/snowflake/client/core/SecureStorageLinuxManager.java @@ -26,11 +26,9 @@ public class SecureStorageLinuxManager implements SecureStorageManager { private static final String CACHE_FILE_NAME = "temporary_credential.json"; private static final String CACHE_DIR_PROP = "net.snowflake.jdbc.temporaryCredentialCacheDir"; private static final String CACHE_DIR_ENV = "SF_TEMPORARY_CREDENTIAL_CACHE_DIR"; - private static final long CACHE_EXPIRATION_IN_SECONDS = 86400L; + private static final String CACHE_FILE_TOKENS_OBJECT_NAME = "tokens"; private static final long CACHE_FILE_LOCK_EXPIRATION_IN_SECONDS = 60L; - private FileCacheManager fileCacheManager; - - private final Map> localCredCache = new HashMap<>(); + private final FileCacheManager fileCacheManager; private SecureStorageLinuxManager() { fileCacheManager = @@ -38,7 +36,6 @@ private SecureStorageLinuxManager() { .setCacheDirectorySystemProperty(CACHE_DIR_PROP) .setCacheDirectoryEnvironmentVariable(CACHE_DIR_ENV) .setBaseCacheFileName(CACHE_FILE_NAME) - .setCacheExpirationInSeconds(CACHE_EXPIRATION_IN_SECONDS) .setCacheFileLockExpirationInSeconds(CACHE_FILE_LOCK_EXPIRATION_IN_SECONDS) .build(); logger.debug( @@ -53,78 +50,93 @@ public static SecureStorageLinuxManager getInstance() { return SecureStorageLinuxManagerHolder.INSTANCE; } - private ObjectNode localCacheToJson() { - ObjectNode res = mapper.createObjectNode(); - for (Map.Entry> elem : localCredCache.entrySet()) { - String elemHost = elem.getKey(); - Map hostMap = elem.getValue(); - ObjectNode hostNode = mapper.createObjectNode(); - for (Map.Entry elem0 : hostMap.entrySet()) { - hostNode.put(elem0.getKey(), elem0.getValue()); - } - res.set(elemHost, hostNode); - } - return res; - } - + @Override public synchronized SecureStorageStatus setCredential( String host, String user, String type, String token) { if (Strings.isNullOrEmpty(token)) { logger.warn("No token provided", false); return SecureStorageStatus.SUCCESS; } - - localCredCache.computeIfAbsent(host.toUpperCase(), newMap -> new HashMap<>()); - - Map hostMap = localCredCache.get(host.toUpperCase()); - hostMap.put(SecureStorageManager.convertTarget(host, user, type), token); - - fileCacheManager.writeCacheFile(localCacheToJson()); + fileCacheManager.withLock( + () -> { + Map> cachedCredentials = + readJsonStoreCache(fileCacheManager.readCacheFile()); + cachedCredentials.computeIfAbsent( + CACHE_FILE_TOKENS_OBJECT_NAME, tokensMap -> new HashMap<>()); + Map credentialsMap = cachedCredentials.get(CACHE_FILE_TOKENS_OBJECT_NAME); + credentialsMap.put(SecureStorageManager.buildCredentialsKey(host, user, type), token); + fileCacheManager.writeCacheFile( + SecureStorageLinuxManager.this.localCacheToJson(cachedCredentials)); + return null; + }); return SecureStorageStatus.SUCCESS; } + @Override public synchronized String getCredential(String host, String user, String type) { - JsonNode res = fileCacheManager.readCacheFile(); - readJsonStoreCache(res); - - Map hostMap = localCredCache.get(host.toUpperCase()); - - if (hostMap == null) { - return null; - } - - return hostMap.get(SecureStorageManager.convertTarget(host, user, type)); + return fileCacheManager.withLock( + () -> { + JsonNode res = fileCacheManager.readCacheFile(); + Map> cache = readJsonStoreCache(res); + Map credentialsMap = cache.get(CACHE_FILE_TOKENS_OBJECT_NAME); + if (credentialsMap == null) { + return null; + } + return credentialsMap.get(SecureStorageManager.buildCredentialsKey(host, user, type)); + }); } - /** May delete credentials which doesn't belong to this process */ + @Override public synchronized SecureStorageStatus deleteCredential(String host, String user, String type) { - Map hostMap = localCredCache.get(host.toUpperCase()); - if (hostMap != null) { - hostMap.remove(SecureStorageManager.convertTarget(host, user, type)); - if (hostMap.isEmpty()) { - localCredCache.remove(host.toUpperCase()); + fileCacheManager.withLock( + () -> { + JsonNode res = fileCacheManager.readCacheFile(); + Map> cache = readJsonStoreCache(res); + Map credentialsMap = cache.get(CACHE_FILE_TOKENS_OBJECT_NAME); + if (credentialsMap != null) { + credentialsMap.remove(SecureStorageManager.buildCredentialsKey(host, user, type)); + if (credentialsMap.isEmpty()) { + cache.remove(CACHE_FILE_TOKENS_OBJECT_NAME); + } + } + fileCacheManager.writeCacheFile(localCacheToJson(cache)); + return null; + }); + return SecureStorageStatus.SUCCESS; + } + + private ObjectNode localCacheToJson(Map> cache) { + ObjectNode res = mapper.createObjectNode(); + for (Map.Entry> elem : cache.entrySet()) { + String elemHost = elem.getKey(); + Map hostMap = elem.getValue(); + ObjectNode hostNode = mapper.createObjectNode(); + for (Map.Entry elem0 : hostMap.entrySet()) { + hostNode.put(elem0.getKey(), elem0.getValue()); } + res.set(elemHost, hostNode); } - fileCacheManager.writeCacheFile(localCacheToJson()); - return SecureStorageStatus.SUCCESS; + return res; } - private void readJsonStoreCache(JsonNode m) { - if (m == null || !m.getNodeType().equals(JsonNodeType.OBJECT)) { + private Map> readJsonStoreCache(JsonNode node) { + Map> credentialsCache = new HashMap<>(); + if (node == null || !node.getNodeType().equals(JsonNodeType.OBJECT)) { logger.debug("Invalid cache file format."); - return; + return credentialsCache; } - for (Iterator> itr = m.fields(); itr.hasNext(); ) { + for (Iterator> itr = node.fields(); itr.hasNext(); ) { Map.Entry hostMap = itr.next(); String host = hostMap.getKey(); - if (!localCredCache.containsKey(host)) { - localCredCache.put(host, new HashMap<>()); + if (!credentialsCache.containsKey(host)) { + credentialsCache.put(host, new HashMap<>()); } JsonNode userJsonNode = hostMap.getValue(); for (Iterator> itr0 = userJsonNode.fields(); itr0.hasNext(); ) { Map.Entry userMap = itr0.next(); - localCredCache.get(host).put(userMap.getKey(), userMap.getValue().asText()); + credentialsCache.get(host).put(userMap.getKey(), userMap.getValue().asText()); } } + return credentialsCache; } } diff --git a/src/main/java/net/snowflake/client/core/SecureStorageManager.java b/src/main/java/net/snowflake/client/core/SecureStorageManager.java index d64c26c38..485e7e316 100644 --- a/src/main/java/net/snowflake/client/core/SecureStorageManager.java +++ b/src/main/java/net/snowflake/client/core/SecureStorageManager.java @@ -4,12 +4,14 @@ package net.snowflake.client.core; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + /** * Interface for accessing Platform specific Local Secure Storage E.g. keychain on Mac credential * manager on Windows */ interface SecureStorageManager { - String DRIVER_NAME = "SNOWFLAKE-JDBC-DRIVER"; int COLON_CHAR_LENGTH = 1; SecureStorageStatus setCredential(String host, String user, String type, String token); @@ -18,24 +20,23 @@ interface SecureStorageManager { SecureStorageStatus deleteCredential(String host, String user, String type); - static String convertTarget(String host, String user, String type) { + static String buildCredentialsKey(String host, String user, String type) { StringBuilder target = - new StringBuilder( - host.length() - + user.length() - + DRIVER_NAME.length() - + type.length() - + 3 * COLON_CHAR_LENGTH); + new StringBuilder(host.length() + user.length() + type.length() + 3 * COLON_CHAR_LENGTH); target.append(host.toUpperCase()); target.append(":"); target.append(user.toUpperCase()); target.append(":"); - target.append(DRIVER_NAME); - target.append(":"); target.append(type.toUpperCase()); - return target.toString(); + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] hash = md.digest(target.toString().getBytes()); + return SFTrustManager.byteToHexString(hash); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } } enum SecureStorageStatus { diff --git a/src/main/java/net/snowflake/client/core/SecureStorageWindowsManager.java b/src/main/java/net/snowflake/client/core/SecureStorageWindowsManager.java index e47a6d88b..0cf6e5ff5 100644 --- a/src/main/java/net/snowflake/client/core/SecureStorageWindowsManager.java +++ b/src/main/java/net/snowflake/client/core/SecureStorageWindowsManager.java @@ -47,7 +47,7 @@ public SecureStorageStatus setCredential(String host, String user, String type, Memory credBlobMem = new Memory(credBlob.length); credBlobMem.write(0, credBlob, 0, credBlob.length); - String target = SecureStorageManager.convertTarget(host, user, type); + String target = SecureStorageManager.buildCredentialsKey(host, user, type); SecureStorageWindowsCredential cred = new SecureStorageWindowsCredential(); cred.Type = SecureStorageWindowsCredentialType.CRED_TYPE_GENERIC.getType(); @@ -76,7 +76,7 @@ public SecureStorageStatus setCredential(String host, String user, String type, public String getCredential(String host, String user, String type) { PointerByReference pCredential = new PointerByReference(); - String target = SecureStorageManager.convertTarget(host, user, type); + String target = SecureStorageManager.buildCredentialsKey(host, user, type); try { boolean ret = false; @@ -127,7 +127,7 @@ public String getCredential(String host, String user, String type) { } public SecureStorageStatus deleteCredential(String host, String user, String type) { - String target = SecureStorageManager.convertTarget(host, user, type); + String target = SecureStorageManager.buildCredentialsKey(host, user, type); boolean ret = false; synchronized (advapi32Lib) { diff --git a/src/main/java/net/snowflake/client/core/SessionUtil.java b/src/main/java/net/snowflake/client/core/SessionUtil.java index 7711539f9..32fbc6e0e 100644 --- a/src/main/java/net/snowflake/client/core/SessionUtil.java +++ b/src/main/java/net/snowflake/client/core/SessionUtil.java @@ -31,7 +31,6 @@ import net.snowflake.client.core.auth.oauth.AccessTokenProvider; import net.snowflake.client.core.auth.oauth.OAuthAccessTokenForRefreshTokenProvider; import net.snowflake.client.core.auth.oauth.OAuthAccessTokenProviderFactory; -import net.snowflake.client.core.auth.oauth.OAuthUtil; import net.snowflake.client.core.auth.oauth.TokenResponseDTO; import net.snowflake.client.jdbc.ErrorCode; import net.snowflake.client.jdbc.SnowflakeDriver; @@ -606,10 +605,6 @@ static SFLoginOutput newSession( if (authenticatorType == AuthenticatorType.OAUTH && loginInput.getOriginalAuthenticator() != null) { data.put(ClientAuthnParameter.OAUTH_TYPE.name(), loginInput.getOriginalAuthenticator()); - URI idpUri = - OAuthUtil.getTokenRequestUrl( - loginInput.getOauthLoginInput(), loginInput.getServerUrl()); - data.put(ClientAuthnParameter.IDP_HOST.name(), idpUri.getHost()); } // map of client environment parameters, including connection parameters diff --git a/src/main/java/net/snowflake/client/core/auth/ClientAuthnParameter.java b/src/main/java/net/snowflake/client/core/auth/ClientAuthnParameter.java index 9a6f89057..95517fd45 100644 --- a/src/main/java/net/snowflake/client/core/auth/ClientAuthnParameter.java +++ b/src/main/java/net/snowflake/client/core/auth/ClientAuthnParameter.java @@ -21,6 +21,5 @@ public enum ClientAuthnParameter { SESSION_PARAMETERS, PROOF_KEY, TOKEN, - OAUTH_TYPE, - IDP_HOST + OAUTH_TYPE } diff --git a/src/main/java/net/snowflake/client/core/auth/oauth/OAuthUtil.java b/src/main/java/net/snowflake/client/core/auth/oauth/OAuthUtil.java index 968a49a00..46906dce7 100644 --- a/src/main/java/net/snowflake/client/core/auth/oauth/OAuthUtil.java +++ b/src/main/java/net/snowflake/client/core/auth/oauth/OAuthUtil.java @@ -10,21 +10,18 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import net.snowflake.client.core.SFOauthLoginInput; -import net.snowflake.client.core.SnowflakeJdbcInternalApi; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.StringEntity; -@SnowflakeJdbcInternalApi -public class OAuthUtil { +class OAuthUtil { private static final String SNOWFLAKE_AUTHORIZE_ENDPOINT = "/oauth/authorize"; private static final String SNOWFLAKE_TOKEN_REQUEST_ENDPOINT = "/oauth/token-request"; private static final String DEFAULT_SESSION_ROLE_SCOPE_PREFIX = "session:role:"; - @SnowflakeJdbcInternalApi - public static URI getTokenRequestUrl(SFOauthLoginInput oauthLoginInput, String serverUrl) { + static URI getTokenRequestUrl(SFOauthLoginInput oauthLoginInput, String serverUrl) { URI uri = !StringUtils.isNullOrEmpty(oauthLoginInput.getExternalTokenRequestUrl()) ? URI.create(oauthLoginInput.getExternalTokenRequestUrl()) diff --git a/src/test/java/net/snowflake/client/core/FileCacheManagerTest.java b/src/test/java/net/snowflake/client/core/FileCacheManagerTest.java index 023c20d40..521e48702 100644 --- a/src/test/java/net/snowflake/client/core/FileCacheManagerTest.java +++ b/src/test/java/net/snowflake/client/core/FileCacheManagerTest.java @@ -54,7 +54,6 @@ public void setup() throws IOException { .setCacheDirectorySystemProperty(CACHE_DIR_PROP) .setCacheDirectoryEnvironmentVariable(CACHE_DIR_ENV) .setBaseCacheFileName(CACHE_FILE_NAME) - .setCacheExpirationInSeconds(CACHE_EXPIRATION_IN_SECONDS) .setCacheFileLockExpirationInSeconds(CACHE_FILE_LOCK_EXPIRATION_IN_SECONDS) .build(); cacheFile = createCacheFile(); diff --git a/src/test/java/net/snowflake/client/core/SecureStorageManagerTest.java b/src/test/java/net/snowflake/client/core/SecureStorageManagerTest.java index b79875038..5e6181fe5 100644 --- a/src/test/java/net/snowflake/client/core/SecureStorageManagerTest.java +++ b/src/test/java/net/snowflake/client/core/SecureStorageManagerTest.java @@ -20,6 +20,7 @@ import net.snowflake.client.annotations.RunOnMac; import net.snowflake.client.annotations.RunOnWindows; import net.snowflake.client.annotations.RunOnWindowsOrMac; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class MockAdvapi32Lib implements SecureStorageWindowsManager.Advapi32Lib { @@ -224,6 +225,34 @@ public class SecureStorageManagerTest { private static final String ID_TOKEN = "ID_TOKEN"; private static final String MFA_TOKEN = "MFATOKEN"; + @Test + public void testBuildCredentialsKey() { + // hex values obtained using https://emn178.github.io/online-tools/sha256.html + String hashedKey = + SecureStorageManager.buildCredentialsKey( + host, user, CachedCredentialType.OAUTH_ACCESS_TOKEN.getValue()); + Assertions.assertEquals( + "A7C7EBB89312E88552CD00664A0E20929801FACFBD682BF7C2363FB6EC8F914E", hashedKey); + + hashedKey = + SecureStorageManager.buildCredentialsKey( + host, user, CachedCredentialType.OAUTH_REFRESH_TOKEN.getValue()); + Assertions.assertEquals( + "DB37028833FA02B125FBD6DE8CE679C7E62E7D38FAC585E98060E00987F96772", hashedKey); + + hashedKey = + SecureStorageManager.buildCredentialsKey( + host, user, CachedCredentialType.ID_TOKEN.getValue()); + Assertions.assertEquals( + "6AA3F783E07D1D2182DAB59442806E2433C55C2BD4D9240790FD5B4B91FD4FDB", hashedKey); + + hashedKey = + SecureStorageManager.buildCredentialsKey( + host, user, CachedCredentialType.MFA_TOKEN.getValue()); + Assertions.assertEquals( + "9D10D4EFE45605D85993C6AC95334F1B63D36611B83615656EC7F277A947BF4B", hashedKey); + } + @Test @RunOnWindowsOrMac public void testLoadNativeLibrary() {