-
Notifications
You must be signed in to change notification settings - Fork 33
[FEATURE] Adding token cache to u2m oauth #429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
eb0fad0
e8080b3
b57f6e2
6f1b69d
d8c366e
3dad770
c9fc008
c4433de
9ce45ef
174c3c2
ab64d0f
23b5bd1
ce75413
ef3c000
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -669,4 +669,14 @@ public DatabricksConfig newWithWorkspaceHost(String host) { | |
| "headerFactory")); | ||
| return clone(fieldsToSkip).setHost(host); | ||
| } | ||
|
|
||
| /** | ||
| * Gets the default OAuth redirect URL. If one is not provided explicitly, uses | ||
| * http://localhost:8080/callback | ||
| * | ||
| * @return The OAuth redirect URL to use | ||
| */ | ||
| public String getEffectiveOAuthRedirectUrl() { | ||
| return redirectUrl != null ? redirectUrl : "http://localhost:8080/callback"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is hardcoded at 2 places, making this error prone for future
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i made this change to remove the hardcoded value from 2 places. where else do you mean is this hardcoded?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we separate unrelated refactors such as this into separate PRs?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually added code in ExternalBrowserCredentialsProvider where we would have to define this string "http://localhost:8080/callback" again without the refactor. Thought it would be in scope for this change? |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| package com.databricks.sdk.core.oauth; | ||
|
|
||
| import com.databricks.sdk.core.utils.SerDeUtils; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import java.io.File; | ||
| import java.nio.charset.StandardCharsets; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Path; | ||
| import java.util.Objects; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| /** A TokenCache implementation that stores tokens as plain files. */ | ||
| public class FileTokenCache implements TokenCache { | ||
| private static final Logger LOGGER = LoggerFactory.getLogger(FileTokenCache.class); | ||
|
|
||
| private final Path cacheFile; | ||
| private final ObjectMapper mapper; | ||
|
|
||
| /** | ||
| * Constructs a new SimpleFileTokenCache instance. | ||
| * | ||
| * @param cacheFilePath The path where the token cache will be stored | ||
| */ | ||
| public FileTokenCache(Path cacheFilePath) { | ||
| Objects.requireNonNull(cacheFilePath, "cacheFilePath must be defined"); | ||
|
|
||
| this.cacheFile = cacheFilePath; | ||
| this.mapper = SerDeUtils.createMapper(); | ||
| } | ||
|
|
||
| @Override | ||
| public void save(Token token) { | ||
| try { | ||
| Files.createDirectories(cacheFile.getParent()); | ||
|
|
||
| // Serialize token to JSON | ||
| String json = mapper.writeValueAsString(token); | ||
| byte[] dataToWrite = json.getBytes(StandardCharsets.UTF_8); | ||
|
|
||
| Files.write(cacheFile, dataToWrite); | ||
| // Set file permissions to be readable only by the owner (equivalent to 0600) | ||
| File file = cacheFile.toFile(); | ||
| file.setReadable(false, false); | ||
| file.setReadable(true, true); | ||
| file.setWritable(false, false); | ||
| file.setWritable(true, true); | ||
|
|
||
| LOGGER.debug("Successfully saved token to cache: {}", cacheFile); | ||
| } catch (Exception e) { | ||
| LOGGER.warn("Failed to save token to cache: {}", cacheFile, e); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public Token load() { | ||
| try { | ||
| if (!Files.exists(cacheFile)) { | ||
| LOGGER.debug("No token cache file found at: {}", cacheFile); | ||
| return null; | ||
| } | ||
|
|
||
| byte[] fileContent = Files.readAllBytes(cacheFile); | ||
|
|
||
| // Deserialize token from JSON | ||
| String json = new String(fileContent, StandardCharsets.UTF_8); | ||
| Token token = mapper.readValue(json, Token.class); | ||
| LOGGER.debug("Successfully loaded token from cache: {}", cacheFile); | ||
| return token; | ||
| } catch (Exception e) { | ||
| // If there's any issue loading the token, return null | ||
| // to allow a fresh token to be obtained | ||
| LOGGER.warn("Failed to load token from cache: {}", e.getMessage()); | ||
| return null; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package com.databricks.sdk.core.oauth; | ||
|
|
||
| import com.databricks.sdk.core.DatabricksConfig; | ||
|
|
||
| /** Utility methods for OAuth client credentials resolution. */ | ||
| public class OAuthClientUtils { | ||
|
|
||
| /** Default client ID to use when no client ID is specified. */ | ||
| private static final String DEFAULT_CLIENT_ID = "databricks-cli"; | ||
|
|
||
| /** | ||
| * Resolves the OAuth client ID from the configuration. Prioritizes regular OAuth client ID, then | ||
| * Azure client ID, and falls back to default client ID. | ||
| * | ||
| * @param config The Databricks configuration | ||
| * @return The resolved client ID | ||
| */ | ||
| public static String resolveClientId(DatabricksConfig config) { | ||
| if (config.getClientId() != null) { | ||
| return config.getClientId(); | ||
| } else if (config.getAzureClientId() != null) { | ||
| return config.getAzureClientId(); | ||
| } | ||
| return DEFAULT_CLIENT_ID; | ||
| } | ||
|
|
||
| /** | ||
| * Resolves the OAuth client secret from the configuration. Prioritizes regular OAuth client | ||
| * secret, then Azure client secret. | ||
| * | ||
| * @param config The Databricks configuration | ||
| * @return The resolved client secret, or null if not present | ||
| */ | ||
| public static String resolveClientSecret(DatabricksConfig config) { | ||
| if (config.getClientSecret() != null) { | ||
| return config.getClientSecret(); | ||
| } else if (config.getAzureClientSecret() != null) { | ||
| return config.getAzureClientSecret(); | ||
| } | ||
| return null; | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.