generateCacheKey(ParameterSet parameterSet) {
+ return parameterSet.filterParameters(new String[]{
+ PARAM_HCP_CLIENT_ID, PARAM_HCP_CLIENT_SECRET
+ });
+ }
+}
diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultAuthenticationMethod.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultAuthenticationMethod.java
new file mode 100644
index 00000000..cc52ef50
--- /dev/null
+++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultAuthenticationMethod.java
@@ -0,0 +1,106 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+
+package oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication;
+
+/**
+ * Enumeration of authentication methods supported by HCP Vault Secrets.
+ *
+ * This represents the different ways to authenticate with the HCP Vault Secrets API.
+ *
+ */
+public enum HcpVaultAuthenticationMethod {
+
+ /**
+ * Authentication using client credentials via the OAuth2 client_credentials flow.
+ *
+ * This method requires the following:
+ *
+ *
+ * - A Client ID provided by the HCP Vault console or associated
+ * with an HCP Service Principal.
+ *
+ * - A Client Secret corresponding to the Client ID, ensuring
+ * secure access.
+ *
+ *
+ *
+ * By using these credentials, the method retrieves a short-lived API token
+ * by calling the HCP OAuth2 endpoint.
+ *
+ */
+ CLIENT_CREDENTIALS,
+
+ /**
+ * Authentication using the credentials file generated by the HCP CLI.
+ *
+ * This method retrieves an access token from the standard CLI-generated
+ * credentials file located at
+ * System.getProperty("user.home") + "/.config/hcp/creds-cache.json"
.
+ * If the token is expired,
+ * it will be automatically refreshed using the stored refresh token.
+ *
+ *
+ * The credentials file must follow the standard JSON structure containing:
+ *
+ *
+ * {
+ * "login": {
+ * "access_token": "...",
+ * "refresh_token": "...",
+ * "access_token_expiry": "..."
+ * }
+ * }
+ *
+ *
+ * The user can provide a custom path to the credentials file if needed.
+ *
+ */
+ CLI_CREDENTIALS_FILE,
+
+ /**
+ * Automatically selects the best authentication method based on available parameters.
+ *
+ * Priority order:
+ *
+ * - Uses the credentials file if present and valid.
+ * - Falls back to client credentials authentication.
+ *
+ */
+ AUTO_DETECT;
+}
\ No newline at end of file
diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultCredentialsFileAuthenticator.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultCredentialsFileAuthenticator.java
new file mode 100644
index 00000000..e551925a
--- /dev/null
+++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultCredentialsFileAuthenticator.java
@@ -0,0 +1,246 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+
+package oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication;
+
+import oracle.jdbc.provider.hashicorp.util.HttpUtil;
+import oracle.jdbc.provider.hashicorp.util.JsonUtil;
+import oracle.sql.json.OracleJsonObject;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.Base64;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Handles authentication using the HashiCorp CLI credentials cache.
+ *
+ * This class reads the authentication details from the CLI-generated credentials file
+ * (`creds-cache.json`) and manages the token lifecycle, including:
+ *
+ *
+ * - Validating the access token's expiration.
+ * - Refreshing the token using the stored refresh token when expired.
+ * - Updating the credentials file with the new token details.
+ *
+ *
+ * By default, the credentials file is expected at:
+ * System.getProperty("user.home") + "/.config/hcp/creds-cache.json"
.
+ * However, users can provide a custom file path through configuration.
+ *
+ */
+public final class HcpVaultCredentialsFileAuthenticator {
+ private static final String TOKEN_URL = "https://auth.idp.hashicorp.com/oauth2/token";
+ private static final String GRANT_TYPE = "refresh_token";
+ private static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
+ private static final String TOKEN_REFRESH_PAYLOAD_FORMAT = "grant_type=%s&refresh_token=%s&client_id=%s";
+ private static final String CREDENTIALS_JSON_FORMAT =
+ "{ \"login\": { \"access_token\": \"%s\", \"refresh_token\": \"%s\", \"access_token_expiry\": \"%s\" } }";
+
+ // JSON field constants
+ public static final String ACCESS_TOKEN_FIELD = "access_token";
+ private static final String REFRESH_TOKEN_FIELD = "refresh_token";
+ private static final String ACCESS_TOKEN_EXPIRY_FIELD = "access_token_expiry";
+ private static final String EXPIRES_IN_FIELD = "expires_in";
+ private static final String CLIENT_ID_FIELD = "client_id";
+ private static final String LOGIN_FIELD = "login";
+
+ private final ReentrantLock lock = new ReentrantLock();
+
+ private volatile String accessToken;
+ private volatile String refreshToken;
+ private volatile Instant tokenExpiry;
+
+ private final Path credsFilePath;
+
+ /**
+ * Creates an instance of {@link HcpVaultCredentialsFileAuthenticator} to handle authentication
+ * via the HCP CLI credentials cache file.
+ *
+ * @param credentialsFilePath The path to the credentials file.
+ */
+ public HcpVaultCredentialsFileAuthenticator(String credentialsFilePath) {
+ this.credsFilePath = Paths.get(credentialsFilePath);
+ }
+
+ /**
+ * Retrieves a valid access token, refreshing it if expired.
+ *
+ * @return A valid access token.
+ * @throws IOException if authentication fails.
+ */
+ public String getValidAccessToken() throws Exception {
+ lock.lock();
+ try {
+ if (accessToken == null || isTokenExpired()) {
+ loadCredentials();
+ if (isTokenExpired()) {
+ refreshAccessToken();
+ }
+ }
+ return accessToken;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Loads credentials from the CLI cache file.
+ *
+ * @throws IOException if there is an error reading the file
+ */
+ private void loadCredentials() throws IOException {
+ if (!Files.exists(credsFilePath)) {
+ throw new IOException("HCP Vault credentials file not found: " + credsFilePath);
+ }
+
+ String content = new String(Files.readAllBytes(credsFilePath), StandardCharsets.UTF_8);
+
+ OracleJsonObject rootObject = JsonUtil.convertJsonToOracleJsonObject(content);
+ if (rootObject == null) {
+ throw new IOException("Failed to parse credentials file: invalid JSON format");
+ }
+
+ OracleJsonObject loginObject;
+ try {
+ loginObject = rootObject.getObject(LOGIN_FIELD);
+ } catch (NullPointerException e) {
+ throw new IOException("Invalid credentials file format: missing 'login'" +
+ " object", e);
+ }
+ accessToken = JsonUtil.extractField(loginObject, ACCESS_TOKEN_FIELD);
+ refreshToken = JsonUtil.extractField(loginObject, REFRESH_TOKEN_FIELD);
+
+ String expiryStr = JsonUtil.extractField(loginObject, ACCESS_TOKEN_EXPIRY_FIELD);
+ if (expiryStr != null && !expiryStr.isEmpty()) {
+ tokenExpiry = OffsetDateTime.parse(expiryStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME).toInstant();
+ }
+ }
+
+ /**
+ * Checks if the current token is expired.
+ *
+ * @return true if the token is expired
+ */
+ private boolean isTokenExpired() {
+ return tokenExpiry == null || Instant.now().isAfter(tokenExpiry);
+ }
+
+ /**
+ * Refreshes the access token using the refresh token.
+ *
+ * @throws IOException if the refresh operation fails
+ */
+ private void refreshAccessToken() throws Exception {
+ String clientId = extractClientIdFromToken(accessToken);
+ if (clientId == null || refreshToken == null) {
+ throw new IllegalStateException("Missing required parameters for token refresh.");
+ }
+
+ String payload = String.format(TOKEN_REFRESH_PAYLOAD_FORMAT, GRANT_TYPE, refreshToken, clientId);
+ String jsonResponse = HttpUtil.sendPostRequest(TOKEN_URL, payload, CONTENT_TYPE, null
+ , null);
+
+ OracleJsonObject response = JsonUtil.convertJsonToOracleJsonObject(jsonResponse);
+ updateTokensFromResponse(response);
+ updateCredsFile();
+ }
+
+ /**
+ * Updates tokens and expiry from the refresh response.
+ *
+ * @param response The JSON response from the refresh request
+ */
+ private void updateTokensFromResponse(OracleJsonObject response) {
+ accessToken = JsonUtil.extractField(response, ACCESS_TOKEN_FIELD);
+
+ try {
+ long expiresInSeconds = response.getLong(EXPIRES_IN_FIELD);
+ tokenExpiry = Instant.now().plusSeconds(expiresInSeconds);
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("Missing '" + EXPIRES_IN_FIELD + "' field in token response", e);
+ }
+
+ // Update refresh token if provided
+ String newRefreshToken = JsonUtil.extractField(response, REFRESH_TOKEN_FIELD);
+ if (newRefreshToken != null && !newRefreshToken.isEmpty()) {
+ refreshToken = newRefreshToken;
+ }
+ }
+
+ /**
+ * Updates the credentials cache file with new token information.
+ *
+ * @throws IOException if file writing fails
+ */
+ private void updateCredsFile() throws IOException {
+ String updatedContent = String.format(CREDENTIALS_JSON_FORMAT, accessToken,
+ refreshToken, OffsetDateTime.ofInstant(tokenExpiry, ZoneOffset.UTC).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
+ );
+
+ Files.write(credsFilePath, updatedContent.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * Extracts the client ID from a JWT token.
+ *
+ * @param token The JWT token
+ * @return The extracted client ID
+ * @throws IllegalArgumentException if the token is invalid or client_id extraction fails.
+ */
+ private static String extractClientIdFromToken(String token) {
+ try {
+ String[] parts = token.split("\\.");
+ if (parts.length != 3) {
+ throw new IllegalArgumentException("Invalid JWT token format.");
+ }
+ String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);
+ OracleJsonObject payload = JsonUtil.convertJsonToOracleJsonObject(payloadJson);
+ return JsonUtil.extractField(payload, CLIENT_ID_FIELD);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to extract client_id from JWT token.", e);
+ }
+ }
+}
diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultOAuthClient.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultOAuthClient.java
new file mode 100644
index 00000000..7b1773c3
--- /dev/null
+++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultOAuthClient.java
@@ -0,0 +1,93 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+
+package oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication;
+
+import oracle.jdbc.provider.hashicorp.util.HttpUtil;
+import oracle.jdbc.provider.hashicorp.util.JsonUtil;
+import oracle.sql.json.OracleJsonObject;
+
+import static oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication.HcpVaultCredentialsFileAuthenticator.ACCESS_TOKEN_FIELD;
+
+/**
+ * A client for performing OAuth2 operations with HCP Vault Secrets.
+ *
+ * This class implements the client_credentials flow to obtain an API token
+ * required for interacting with HCP Vault Secrets.
+ *
+ */
+public final class HcpVaultOAuthClient {
+
+ private static final String OAUTH_TOKEN_URL = "https://auth.idp.hashicorp.com/oauth/token";
+ private static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
+ private static final String GRANT_TYPE = "client_credentials";
+ private static final String AUDIENCE = "https://api.hashicorp.cloud";
+ private static final String CLIENT_CREDENTIALS_PAYLOAD_FORMAT =
+ "grant_type=%s&client_id=%s&client_secret=%s&audience=%s";
+
+ private HcpVaultOAuthClient() {}
+
+ /**
+ * Fetches an access token from HCP Vault Secrets using the client_credentials flow.
+ *
+ * @param clientId the OAuth2 client ID. Must not be null or empty.
+ * @param clientSecret the OAuth2 client secret. Must not be null or empty.
+ * @return the access token as a {@code String}. Never null or empty.
+ * @throws IllegalStateException if the token cannot be obtained.
+ */
+ public static String fetchHcpAccessToken(String clientId, String clientSecret) {
+ try {
+ String payload = String.format(
+ CLIENT_CREDENTIALS_PAYLOAD_FORMAT, GRANT_TYPE, clientId, clientSecret, AUDIENCE);
+
+ String jsonResponse = HttpUtil.sendPostRequest(
+ OAUTH_TOKEN_URL,
+ payload,
+ CONTENT_TYPE,
+ null,
+ null
+ );
+ OracleJsonObject response = JsonUtil.convertJsonToOracleJsonObject(jsonResponse);
+ return JsonUtil.extractField(response, ACCESS_TOKEN_FIELD);
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to fetch HCP access token", e);
+ }
+ }
+
+}
diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java
new file mode 100644
index 00000000..80da8158
--- /dev/null
+++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java
@@ -0,0 +1,205 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+
+package oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication;
+
+import oracle.jdbc.provider.hashicorp.util.Parameterutil;
+import oracle.jdbc.provider.parameter.Parameter;
+import oracle.jdbc.provider.parameter.ParameterSet;
+import oracle.jdbc.provider.parameter.ParameterSetParser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication.HcpVaultAuthenticationMethod.AUTO_DETECT;
+import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.*;
+
+/**
+ * Contains parameter definitions for interacting with HCP Vault Secrets.
+ *
+ * This class centralizes configuration parameters used for authenticating
+ * with and retrieving secrets from HCP Vault Secrets.
+ *
+ */
+public class HcpVaultSecretParameters {
+
+ /**
+ * Constants representing the configuration parameter names for HCP Vault Secrets.
+ *
+ * These constants serve as both parameter names within the {@link ParameterSet}
+ * and as keys for environment variables or system properties.
+ *
+ */
+ public static final String PARAM_HCP_ORG_ID = "HCP_ORG_ID";
+ public static final String PARAM_HCP_PROJECT_ID = "HCP_PROJECT_ID";
+ public static final String PARAM_HCP_APP_NAME = "HCP_APP_NAME";
+ public static final String PARAM_HCP_CLIENT_ID = "HCP_CLIENT_ID";
+ public static final String PARAM_HCP_CLIENT_SECRET = "HCP_CLIENT_SECRET";
+ public static final String PARAM_HCP_CREDENTIALS_FILE =
+ "HCP_CREDENTIALS_FILE";
+ private static final String DEFAULT_CREDENTIALS_FILE_PATH =
+ System.getProperty("user.home") + "/.config/hcp/creds-cache.json";
+ private static final String PARAM_AUTHENTICATION = "AUTHENTICATION";
+
+ /**
+ * Parameter indicating the authentication method to use for HCP Vault Secrets.
+ */
+ public static final Parameter AUTHENTICATION_METHOD = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the OAuth2 client ID. Required.
+ */
+ public static final Parameter HCP_CLIENT_ID = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the OAuth2 client secret. Required.
+ */
+ public static final Parameter HCP_CLIENT_SECRET = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the credentials file path.
+ * By default, the credentials file is expected at:
+ * System.getProperty("user.home") + "/.config/hcp/creds-cache.json"
.
+ */
+ public static final Parameter HCP_CREDENTIALS_FILE = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the organization ID. Required.
+ */
+ public static final Parameter HCP_ORG_ID = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the project ID. Required.
+ */
+ public static final Parameter HCP_PROJECT_ID = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the application name. Required.
+ */
+ public static final Parameter HCP_APP_NAME = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the secret name. Required.
+ */
+ public static final Parameter SECRET_NAME = Parameter.create(REQUIRED);
+
+ /**
+ * Parameter for the optional key in the secret JSON.
+ */
+ public static final Parameter KEY = Parameter.create();
+
+ /**
+ * Builds a ParameterSet from the given options map.
+ *
+ * This method makes a defensive copy of the provided map, ensures that a default
+ * authentication method is set, and then fills in missing keys using fallback values
+ * (from system properties or environment variables) based on the authentication method.
+ * Finally, it parses the updated map into a ParameterSet.
+ *
+ *
+ * @param inputOpts The input options map.
+ * @return The ParameterSet.
+ */
+ public static ParameterSet buildResolvedParameterSet(Map inputOpts) {
+ Map opts = new HashMap<>(inputOpts);
+
+ String authStr = opts.entrySet().stream()
+ .filter(entry -> entry.getKey().equalsIgnoreCase(PARAM_AUTHENTICATION))
+ .map(Map.Entry::getValue)
+ .findFirst()
+ .orElse(HcpVaultAuthenticationMethod.AUTO_DETECT.name());
+
+ HcpVaultAuthenticationMethod authMethod =
+ HcpVaultAuthenticationMethod.valueOf(authStr.toUpperCase());
+
+ opts.computeIfAbsent(PARAM_HCP_ORG_ID, Parameterutil::getFallback);
+ opts.computeIfAbsent(PARAM_HCP_PROJECT_ID, Parameterutil::getFallback);
+ opts.computeIfAbsent(PARAM_HCP_APP_NAME, Parameterutil::getFallback);
+
+ switch (authMethod) {
+ case CLIENT_CREDENTIALS:
+ opts.computeIfAbsent(PARAM_HCP_CLIENT_ID, Parameterutil::getFallback);
+ opts.computeIfAbsent(PARAM_HCP_CLIENT_SECRET, Parameterutil::getFallback);
+ break;
+ case CLI_CREDENTIALS_FILE:
+ opts.computeIfAbsent(PARAM_HCP_CREDENTIALS_FILE, Parameterutil::getFallback);
+ break;
+ case AUTO_DETECT:
+ opts.computeIfAbsent(PARAM_HCP_CLIENT_ID, Parameterutil::getFallback);
+ opts.computeIfAbsent(PARAM_HCP_CLIENT_SECRET, Parameterutil::getFallback);
+ opts.computeIfAbsent(PARAM_HCP_CREDENTIALS_FILE, Parameterutil::getFallback);
+ break;
+ default:
+ break;
+ }
+ return PARAMETER_SET_PARSER.parseNamedValues(opts);
+ }
+
+ /**
+ * Parses the authentication method from a string value.
+ *
+ * @param value the string value representing the authentication method. Must
+ * not be null.
+ * @return the parsed {@link HcpVaultAuthenticationMethod}.
+ * @throws IllegalArgumentException if the value is unrecognized.
+ */
+ private static HcpVaultAuthenticationMethod parseAuthMethod(String value) {
+ try {
+ return HcpVaultAuthenticationMethod.valueOf(value.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException(
+ "Unrecognized HCP auth method: " + value, e);
+ }
+ }
+
+ public static final ParameterSetParser PARAMETER_SET_PARSER =
+ ParameterSetParser.builder()
+ .addParameter("value", SECRET_NAME)
+ .addParameter(PARAM_AUTHENTICATION, AUTHENTICATION_METHOD, AUTO_DETECT,
+ HcpVaultSecretParameters::parseAuthMethod)
+ .addParameter(PARAM_HCP_ORG_ID, HCP_ORG_ID)
+ .addParameter(PARAM_HCP_PROJECT_ID, HCP_PROJECT_ID)
+ .addParameter(PARAM_HCP_APP_NAME, HCP_APP_NAME)
+ .addParameter(PARAM_HCP_CLIENT_ID, HCP_CLIENT_ID)
+ .addParameter(PARAM_HCP_CLIENT_SECRET, HCP_CLIENT_SECRET)
+ .addParameter(PARAM_HCP_CREDENTIALS_FILE, HCP_CREDENTIALS_FILE, DEFAULT_CREDENTIALS_FILE_PATH)
+ .addParameter("KEY", KEY)
+ .addParameter("type", Parameter.create())
+ .build();
+
+}
diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretToken.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretToken.java
new file mode 100644
index 00000000..14a2d677
--- /dev/null
+++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretToken.java
@@ -0,0 +1,73 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+
+package oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication;
+
+/**
+ * Represents the credentials required to authenticate with HCP Vault Secrets.
+ *
+ * This class holds the API token obtained from the client_credentials OAuth2 flow.
+ *
+ */
+public final class HcpVaultSecretToken {
+ private final String hcpApiToken;
+
+ /**
+ * Constructs a new {@code HcpVaultSecretToken} object with
+ * the provided API token.
+ *
+ * @param hcpApiToken the token used to authenticate API requests to
+ * the HCP Vault Secret. Must not be null or empty.
+ * @throws IllegalArgumentException if {@code hcpApiToken} is null or empty.
+ */
+ public HcpVaultSecretToken(String hcpApiToken) {
+ if (hcpApiToken == null || hcpApiToken.isEmpty()) {
+ throw new IllegalArgumentException("HCP API token must not be null or empty.");
+ }
+ this.hcpApiToken = hcpApiToken;
+ }
+
+ /**
+ * Returns the HCP API token used for authentication.
+ *
+ * @return the HCP API token as a {@link String}.
+ */
+ public String getHcpApiToken() {
+ return hcpApiToken;
+ }
+}
diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultTokenFactory.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultTokenFactory.java
new file mode 100644
index 00000000..05bfdfb1
--- /dev/null
+++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultTokenFactory.java
@@ -0,0 +1,135 @@
+/*
+ ** Copyright (c) 2025 Oracle and/or its affiliates.
+ **
+ ** The Universal Permissive License (UPL), Version 1.0
+ **
+ ** Subject to the condition set forth below, permission is hereby granted to any
+ ** person obtaining a copy of this software, associated documentation and/or data
+ ** (collectively the "Software"), free of charge and under any and all copyright
+ ** rights in the Software, and any and all patent rights owned or freely
+ ** licensable by each licensor hereunder covering either (i) the unmodified
+ ** Software as contributed to or provided by such licensor, or (ii) the Larger
+ ** Works (as defined below), to deal in both
+ **
+ ** (a) the Software, and
+ ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ ** one is included with the Software (each a "Larger Work" to which the Software
+ ** is contributed by such licensors),
+ **
+ ** without restriction, including without limitation the rights to copy, create
+ ** derivative works of, display, perform, and distribute the Software and make,
+ ** use, sell, offer for sale, import, export, have made, and have sold the
+ ** Software and the Larger Work(s), and to sublicense the foregoing rights on
+ ** either these or other terms.
+ **
+ ** This license is subject to the following condition:
+ ** The above copyright notice and either this complete permission notice or at
+ ** a minimum a reference to the UPL must be included in all copies or
+ ** substantial portions of the Software.
+ **
+ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ** SOFTWARE.
+ */
+
+package oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication;
+
+import oracle.jdbc.AccessToken;
+import oracle.jdbc.driver.oauth.JsonWebToken;
+import oracle.jdbc.provider.factory.Resource;
+import oracle.jdbc.provider.factory.ResourceFactory;
+import oracle.jdbc.provider.parameter.Parameter;
+import oracle.jdbc.provider.parameter.ParameterSet;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
+
+import static oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication.HcpVaultSecretParameters.AUTHENTICATION_METHOD;
+import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.REQUIRED;
+/**
+ * A factory for creating {@link HcpVaultSecretToken} objects for HCP Vault Secrets.
+ *
+ * Implements the client_credentials flow as well as file-based authentication.
+ * The auto-detect mode attempts file-based authentication first, then falls back
+ * to client credentials.
+ *
+ */
+public final class HcpVaultTokenFactory implements ResourceFactory {
+
+ private static final HcpVaultTokenFactory INSTANCE = new HcpVaultTokenFactory();
+
+ private static final ConcurrentHashMap