Using new JDBC extension jars available in Maven Central, the 23c JDBC driver can authenticate with Autonomous Database (ADB-S for example) using tokens issued by Azure AD or OCI IAM without having to write any new code. Just load the jars in an existing Java app and as long as the relevant SDK (OCI or Azure) is properly configured, the application will authenticate with the Database.
This is useful for:
Starting in 23c, the Oracle JDBC driver's capabilities can be extended through service providers. The standard Service Provider Interface is used to define custom providers to be loaded at runtime. There are different types of providers that can be loaded for centralized configuration or specific resources such as the URL or an authentication token. Developers can write their own providers, and the Oracle JDBC development team has built open-source providers that are available in the ojdbc-extensions GitHub project. These providers can be used in production and will be fully supported. They include:
The following diagram illustrates use cases for each provider:
In this article, we will be focusing only on the resource providers for authentication tokens. For more information about Configuration providers, please refer to this blog.
The Open Source providers are available on in the ojdbc-extensions GitHub project and the artifacts available in Maven Central. The following pom.xml changes will load the extensions to your Maven project.
First, you need the artifact that's common to both OCI and Azure:
If you use Azure to manage your users, then you will also need the JDBC extension for Azure. The "ojdbc-provider-azure" depends on the Azure SDK and "ojdbc-provider-opentelemetry" on the OpenTelemetry SDK.
Similarly, if you use OCI to manage your users, then you will also need the JDBC extension for Oracle OCI. The "ojdbc-provider-oci" artifact has a dependency on the OCI SDK and the relevant jars will be downloaded.
Oracle Autonomous Database can be configured for token based authentication with either OCI IAM or Azure AD and the JDBC extensions include a provider for each, so that no code change may be needed in the application.
Oracle Autonomous Database and Microsoft Azure AD can be configured to allow users and applications to connect to the database using their Azure AD credentials. The Oracle documentation provides details about the configuration. This blog explains the configuration of the JDBC provider only. The Azure SDK documentation provides details about how to configure the Java SDK for authentication.
Two JDBC properties must be set to make the driver use the Azure token provider:
In the example below, the JDBC properties are passed in the code:
Connection connect() throws SQLException {
OracleDataSource ds = new OracleDataSource();
Properties prop = new Properties();
prop.put(OracleConnection.CONNECTION_PROPERTY_TOKEN_AUTHENTICATION, "AZURE_SERVICE_PRINCIPAL");
prop.put(OracleConnection.CONNECTION_PROPERTY_AZURE_DB_APP_ID_URI, "https://oracledevelopment.onmicrosoft.com/XYZ-gg9b-403a-9863-ZXY");
ds.setConnectionProperties(prop);
ds.setURL("jdbc:oracle:thin:@(description=(address=(protocol=tcps)(port=1521)(host=adb.eu-marseille-1.oraclecloud.com))(connect_data=(service_name=dkjd12000_abcdefg_tp.adb.oraclecloud.com)))");
Connection conn = ds.getConnection();
return conn;
}
If you don't want to change your DataSource properties, you can also pass these properties through Java System properties or directly in the URL. For example:
jdbc:oracle:thin:@(description=(address=(protocol=tcps)(port=1521)(host=adb.eu-marseille-1.oraclecloud.com))(connect_data=(service_name=dkjd12000_abcdefg_tp.adb.oraclecloud.com)))?oracle.jdbc.tokenAuthentication=AZURE_SERVICE_PRINCIPAL&oracle.jdbc.azureDatabaseApplicationIdUri=https://oracledevelopment.onmicrosoft.com/XYZ-gg9b-403a-9863-ZXY
And the following environment variables will be used by the Azure SDK for authentication: AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET. Note that there are other techniques to configure the authentication of the Azure SDK, for example you could use a SEPS wallet to store the CLIENT_ID and CLIENT_SECRET, but in the case of a Service Principal the environment variables will work nicely.
AZURE_TENANT_ID=XYZ-c2e2-4f46-b4t5-ZYX
AZURE_CLIENT_ID=89ad15cc-kze6-4189-9d69-3500000dd6c630
AZURE_CLIENT_SECRET=jbP8Q~wbCTVSr5y7UkbjExg4WK9aNgOT75g7mcKw
AZURE_LOG_LEVEL=VERBOSE
If your Java application is running in an Azure VM, you can configure OracleConnection.CONNECTION_PROPERTY_TOKEN_AUTHENTICATION to "AZURE_MANAGED_IDENTITY" and the SDK authentication configuration will be taken care of by Azure. Note that you will still need to configure CONNECTION_PROPERTY_AZURE_DB_APP_ID_URI.
In the interactive mode, the provider will pop-up a browser window and ask the user to authenticate on the Azure console. In this case there is no need to configure the Azure SDK for authentication. The Azure Documentation says "This credential interactively authenticates a user with the default system browser and offers a smooth authentication experience by letting you use your own credentials to authenticate your application".
You can configure Autonomous Database to use Oracle Cloud Infrastructure Identity and Access Management (IAM) authentication and authorization to allow IAM users to access an Autonomous Database with IAM credentials. Please refer to the documentation for details about how to configure IAM and the DB with token. This blog explains the configuration of the JDBC provider only.
The OCI SDK that is used by the JDBC extensions supports multiple authentication methods:
This section discusses each method in detail and provides examples.
In this authentication method, you create a configuration file and store it on the local disk. The configuration file contains details such as the user OCID, tenancy OCID, region, private key path, and fingerprint. This authentication method creates a permanent configuration file on your machine. It should be used if you are working from a secure network and are comfortable storing private keys and configuration locally.
The following JDBC property must be set to use the API key-based authentication
It's assuming there is a default OCI config file "~/.oci/config", and a profile in that config with the name "DEFAULT". The JDBC properties oracle.jdbc.ociConfigFile, oracle.jdbc.ociProfile, oracle.jdbc.ociTenancy and oracle.jdbc.ociCompartment can be used to use the non-default profile.
Below is a more complete code sample:
Connection connect() throws SQLException {
OracleDataSource ds = new OracleDataSource();
Properties prop = new Properties();
prop.put(OracleConnection.CONNECTION_PROPERTY_TOKEN_AUTHENTICATION, "OCI_API_KEY");
ds.setConnectionProperties(prop);
ds.setURL("jdbc:oracle:thin:@(description=(address=(protocol=tcps)(port=1521)(host=adb.eu-marseille-1.oraclecloud.com))(connect_data=(service_name=dkjd12000_abcdefg_tp.adb.oraclecloud.com)))");
OracleConnection conn = (OracleConnection)ds.getConnection();
return conn;
}
Using instance principal authentication, you can authorize an instance to make calls to OCI IAM. After you set up the required resources and policies, an application running on an instance can call Oracle Cloud Infrastructure public services, removing the need to configure user credentials or a configuration file. For more details, see instance principal.
Instance principal authentication can be used from an instance or VM where you don't want to store a configuration file.
The following JDBC properties must be set to use the API key-based authentication
In the interactive mode, the provider will pop-up a browser window to let the user authenticate with OCI IAM. This gives Single-Sign-On SSO capability.
The following JDBC property must be set to make the driver use the JDBC OCI provider:
Jean de Lavarene is Senior Director of Software Development responsible for the teams that develop the Database drivers, the connection pools (with load balancing and connection failover), the connectors for Hadoop and Spark, the secure access to Data in the Cloud and the high availability features of the Database for Java applications.