23c JDBC seamless authentication with OCI IAM and Azure AD

December 6, 2023 | 6 minute read
Jean de Lavarene
Senior Director of Software Development
Text Size 100%:

TL;DR

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:

  • Java GUI applications in which the end user (DBA or developer) needs to authenticate to connect to the Database.
  • Applications defined as service principals that can authenticate using tokens without the need to manage passwords.
  • In all applications where the security model requires that authentication and authorization is handled through a service like IAM for SSO purposes.

Introduction

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:

  • Configuration provider retrieves the JDBC DataSource configuration from a centralized place
    • OCI DBTools Connection
    • Azure App Configuration
  • Resource provider
    • Trace event listener provider to publish JDBC events into OpenTelemetry
    • Authentication tokens issued by OCI IAM or Azure AD
    • Database password or username stored in a Vault secret
    • JDBC URL for an Autonomous Database

The following diagram illustrates use cases for each provider:

JDBC Extensions architecture

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.

Source code and installation

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.

Seamless token-based authentication with Oracle Autonomous Database

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.

Authentication with Azure Active Directory

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.

Azure Service Principal

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

Azure Managed Identity

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.

Azure Interactive mode

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".

 

Authentication with OCI IAM

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:

  • API key-based authentication
  • Session token-based authentication
  • Instance principal
  • Resource principal

This section discusses each method in detail and provides examples.

API key-based authentication

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.ociConfigFileoracle.jdbc.ociProfileoracle.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;
  }

Instance Principal Authentication

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

OCI Interactive

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

Senior Director of Software Development

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. 


Previous Post

5 Practical SuiteScript 2.1 User Event Scripts with TypeScript

Mohammed Kassem | 7 min read

Next Post


MicroTx Enterprise Edition is Now Available

Todd Little | 3 min read