Skip to content

Conversation

@vikrantpuppala
Copy link
Collaborator

Description

Adds support for token cache to the JDBC driver, specifically adding two parameters: EnableTokenCache and TokenCachePassPhrase

Testing

Manual and unit tests

Additional Notes to the Reviewer

@vikrantpuppala vikrantpuppala requested a review from Copilot April 1, 2025 06:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds token cache support for U2M OAuth in the JDBC driver. The changes include:

  • Introducing a new TokenCache implementation with encryption to persist tokens.
  • Adding comprehensive tests for token caching behavior and the caching credentials provider.
  • Updating configuration classes and URL parameters to support the new TokenCachePassPhrase parameter.

Reviewed Changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/test/java/com/databricks/jdbc/dbclient/impl/common/ClientConfiguratorTest.java Added tests verifying behavior with a valid passphrase and error handling when missing.
src/test/java/com/databricks/jdbc/auth/TokenCacheTest.java New tests for saving, loading, and error conditions in token caching.
src/test/java/com/databricks/jdbc/auth/CachingExternalBrowserCredentialsProviderTest.java New tests to verify both the token refresh and browser authentication fallback logic.
src/main/java/com/databricks/jdbc/dbclient/impl/common/ClientConfigurator.java Modified to use the caching credentials provider for U2M OAuth.
src/main/java/com/databricks/jdbc/common/DatabricksJdbcUrlParams.java Added a new URL parameter for TokenCachePassPhrase.
src/main/java/com/databricks/jdbc/auth/TokenCache.java New implementation for encrypted token caching.
src/main/java/com/databricks/jdbc/auth/CachingExternalBrowserCredentialsProvider.java New credentials provider implementation with token caching and refresh support.
src/main/java/com/databricks/jdbc/api/impl/DatabricksConnectionContext.java and src/main/java/com/databricks/jdbc/api/IDatabricksConnectionContext.java Added a getter for the token cache passphrase.
Files not reviewed (1)
  • pom.xml: Language not supported

# Conflicts:
#	src/main/java/com/databricks/jdbc/api/IDatabricksConnectionContext.java
#	src/main/java/com/databricks/jdbc/api/impl/DatabricksConnectionContext.java
#	src/main/java/com/databricks/jdbc/common/DatabricksJdbcUrlParams.java
#	src/main/java/com/databricks/jdbc/dbclient/impl/common/ClientConfigurator.java
…n-cache

# Conflicts:
#	src/main/java/com/databricks/jdbc/api/IDatabricksConnectionContext.java
#	src/main/java/com/databricks/jdbc/api/impl/DatabricksConnectionContext.java
#	src/main/java/com/databricks/jdbc/common/DatabricksJdbcUrlParams.java
@vikrantpuppala vikrantpuppala requested a review from Copilot April 2, 2025 08:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces support for token caching in the JDBC driver’s OAuth flow, enabling caching of tokens through the addition of two new URL parameters and corresponding tests. Key changes include:

  • Adding new URL parameters (EnableTokenCache and TokenCachePassPhrase) in the connection context.
  • Implementing a TokenCache class that encrypts and persists OAuth tokens.
  • Extending authentication flows in the ClientConfigurator and CachingExternalBrowserCredentialsProvider to leverage cached tokens.

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/test/java/com/databricks/jdbc/dbclient/impl/common/ClientConfiguratorTest.java Updated tests to expect "external-browser-with-cache" auth type and a token passphrase setting
src/test/java/com/databricks/jdbc/auth/TokenCacheTest.java Added tests for saving, loading, and validating token cache behavior
src/test/java/com/databricks/jdbc/auth/CachingExternalBrowserCredentialsProviderTest.java Added tests confirming correct provider behavior with valid, expired, and missing tokens
src/test/java/com/databricks/jdbc/api/impl/DatabricksConnectionContextTest.java Added tests to verify token cache enablement based on URL parameters
src/main/java/com/databricks/jdbc/dbclient/impl/common/ClientConfigurator.java Updated to use the caching provider based on token cache enablement
src/main/java/com/databricks/jdbc/common/DatabricksJdbcUrlParams.java Introduced TOKEN_CACHE_PASS_PHRASE and ENABLE_TOKEN_CACHE parameters
src/main/java/com/databricks/jdbc/auth/TokenCache.java New implementation to encrypt and cache tokens locally
src/main/java/com/databricks/jdbc/auth/CachingExternalBrowserCredentialsProvider.java New provider implementation which leverages cached tokens
src/main/java/com/databricks/jdbc/api/impl/DatabricksConnectionContext.java Implemented accessors for token cache passphrase and enablement flag
src/main/java/com/databricks/jdbc/api/IDatabricksConnectionContext.java Updated interface to include token cache methods
Files not reviewed (1)
  • pom.xml: Language not supported
Comments suppressed due to low confidence (2)

src/main/java/com/databricks/jdbc/auth/TokenCache.java:109

  • Consider specifying an explicit cipher transformation (e.g., 'AES/CBC/PKCS5Padding') instead of relying on default behavior to ensure consistency across environments.
Cipher cipher = Cipher.getInstance(ALGORITHM);

src/main/java/com/databricks/jdbc/common/DatabricksJdbcUrlParams.java:110

  • [nitpick] Consider renaming 'TokenCachePassPhrase' to 'TokenCachePassphrase' for consistency with common terminology and with the rest of the codebase.
TOKEN_CACHE_PASS_PHRASE("TokenCachePassPhrase", "Pass phrase to use for OAuth U2M Token Cache"),

@vikrantpuppala vikrantpuppala changed the title [PECOBLR-131] Add token cache for U2M OAuth [PECOBLR-131][PECOBLR-180] Add token cache for U2M OAuth Apr 7, 2025
* @param context The connection context containing OAuth configuration parameters
* @param tokenCache The token cache to use for storing and retrieving tokens
*/
public CachingExternalBrowserCredentialsProvider(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are reusing lots of code from SDK. Can we do a better structure of class to reuse ExternalBrowserCredentialsProvider from SDK?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExternalBrowserCredentialsProvider does the hand-off to SessionCredentials internally. I was initially trying to overload those classes but it wouldn't just work

* <p>This approach minimizes the need for users to repeatedly authenticate through the browser,
* improving the user experience while maintaining security through encryption of the cached tokens.
*/
public class CachingExternalBrowserCredentialsProvider extends RefreshableTokenSource
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we check with SDK team if we should add this in SDK? Looks useful for other clients as well.

try {
LOGGER.debug("Using refresh token to get new access token");
Token refreshedToken = refreshAccessToken();
tokenCache.save(refreshedToken);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, is this TokenCache the only diff with SDK implementation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially, yes, + the logic on how/when to use token cache

@VisibleForTesting
public TokenCache(Path cacheFile, String passphrase) {
if (passphrase == null || passphrase.isEmpty()) {
throw new IllegalArgumentException(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log this error

byte[] encrypted = encrypt(json.getBytes());
Files.write(cacheFile, encrypted);
} catch (Exception e) {
throw new IOException("Failed to save token cache: " + e.getMessage(), e);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add logging

byte[] decrypted = decrypt(encrypted);
return mapper.readValue(decrypted, SerializableToken.class);
} catch (Exception e) {
throw new IOException("Failed to load token cache: " + e.getMessage(), e);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here also

byte[] decrypted = decrypt(encrypted);
return mapper.readValue(decrypted, SerializableToken.class);
} catch (Exception e) {
throw new IOException("Failed to load token cache: " + e.getMessage(), e);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens to IOException? Do we catch it any upstream class and handle it?

@vikrantpuppala
Copy link
Collaborator Author

Closing in favour of #783

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants