Accessing Autonomous Database with IAM token using Java

January 27, 2022 | 5 minute read
Nirmala Sundarappa
Principal Product Manager
Jean de Lavarene
Senior Director of Software Development
Michael McMahon
Java Developer
Text Size 100%:

Identity and Access Management (IAM) Token Authentication

Oracle now supports Identity and Access Management (IAM) token-based authentication for the Autonomous Database-Shared (ADBS) to simplify and securely manage database passwords in one central place.

The IAM authenticated user can request a database token generated using their existing security session token or API key using the OCI Command Line Interface (CLI) or the OCI SDK. IAM returns the database token that is valid for one hour and its associated private key used as a "Proof-of-Possession (PoP)".  Java applications can then use this IAM database token for connecting to the Autonomous Database. The JDBC driver sends the IAM database token during authentication and a private key signature. If the token and signature are valid, and a mapping exists between the IAM user and a database schema user, access is granted to the database schema user.

IAM token authentication requires 19.13.0.0.1 or 21.4.0.0.1 JDBC drivers (or later). You can get these from Central Maven or download them from the OTN download page. This blog explains the steps for Java applications to successfully generate an IAM token, use it for authentication, and connect to the Oracle Autonomous Database. 

Step 1: Download the JDBC driver that supports IAM-Token authentication 

Download 19.13.0.0.1 or 21.4.0.0.1 JDBC drivers and UCP (if you are using UCP) from Central Maven or OTN. Make sure to update your classpath with the JDBC driver jar files (either ojdbc8.jar or ojdbc11.jar)

Step 2: Enable IAM as external authentication on the database server and create a database user

You must enable IAM-token authentication as "allowed external authentication" on your autonomous database. Log on to your autonomous database and execute the SQL statements.

Although there are many ways to achieve this, the easiest way is to log on to your cloud console, go to your Autonomous Database, click on "Database Actions", and log in with ADMIN and password. Under the 'Development' section, click on 'SQL' and execute the following SQL statements. 

Note that Identity_provider_type will be 'NONE'in the beginning. After enabling the external authentication, it should show "OCI_IAM". 

As shown below, a new database user (example:db_token_userneeds to be associated with the IAM_PRINCIPAL_NAME. Set IAM_PRINCIPAL_NAME to the name of a user managed by IAM. Click on the profile icon in the top right to find the name of the user. To see the name of any other IAM user, type “Users” in the top search bar, and choose the “Users”. Names are listed under the “Name” column. Remove any prefix before the name to get your IAM_PRINCIPAL_NAME. Example: testuser@oracle.com 

 

Alternatively, create an IAM group called "iam_admin_grp", and a policy is defined to allow members of this group to use the resource called "autonomous-database-family".  As shown below, the database user called "db_token_user" used by any IAM user is part of the group "iam_admin_grp". For more details on creating IAM users, groups, and policies, refer to Create IAM Groups and Policies for IAM users

Step 3: Create a DB-token either using the Oracle CLI Utility or the OCI-SDK APIs

There are two ways to request the IAM database token for connecting to the Autonomous Database. Make sure to complete Step 1 and Step 2 above before choosing any of these options. 

Option 1: Use the OCI SDK to request the database token. The following sample code generates the token and establishes the connection to your Autonomous Database. Download JDBCTokenAuthentication.java from GitHub and update the DATABASE_URL to point to the Autonomous Database and OCI_PROFILE to "DEFAULT". Refer to the following guide to populate the config file using your client credentials. The "DEFAULT" labeled configuration from ~$HOME/.oci/config file is picked up. If ADB requires a wallet, then set TNS_ADMIN to point to the wallet's location. The code sample JDBCTokenAuthentication.java also has changes needed to use Instance Principal and Resource Principal as authentication mechanisms as shown below.

authentication = new InstancePrincipalAuthenticationDetailsProvider();
authentication = new ResoucePrincipalAuthenticationDetailsProvider();


Option 2: Use the OCI-CLI to retrieve the IAM database token and store it in a file. Install Oracle Cloud Infrastructure (OCI) Command Line Interface (CLI) locally on your computer. Make sure you are using OCI-CLI v3.4.1 or later. (Run $oci -v to see the version)

OCI-CLI uses ~$HOME/.oci/ location a.k.a OCI_HOME when retrieving the IAM database token and related public and private keys. Make sure you have created a ~$HOME/.oci/config file with the cloud credentials pointing to the Autonomous Database you want to access. The one marked as [DEFAULT] will be the one that the IAM token will be associated with by default. Refer to the following guide to populate the config file using your client credentials. Use the following command to generate the IAM database token valid for 1 hour.

➜ oci iam db-token get
Output: Private key written at /Users/test/.oci/db-token/oci_db_key.pem
db-token written at: /Users/test/.oci/db-token/token
db-token is valid until 2022-01-09 20:02:49

NEW CAPABILITY: OCI-CLI can also be used by passing the Instance Principal and Resource Principal as authentication mechanisms to generate the IAM database token with several other authentication types. This value can also be provided through the OCI_CLI_AUTH environment variable. The default option is "api_key" in which case, the API key in the config file will be used. 

➜ oci --auth[api_key | Instance_principal | security_token | instance_obo_user| resource_principal] iam db-token get

Example: 

➜ oci --auth instance_principal iam db-token get
➜ oci --auth resource_principal iam db-token get

Step 4: Pass a JDBC connection property to indicate IAM database token authentication 

Providing the database username or password isn't required; however, along with the connection string, set a JDBC connection property oracle.jdbc.tokenAuthentication to "OCI_TOKEN" to indicate IAM database token authentication. (You can skip this step if you use Step 3, Option 1). 

As with most JDBC properties, this property can be set either directly in the JDBC URL (Option 1 below) or programmatically (Option 2 below)

Option 1: The IAM token-related property can be passed as part of the connection URL (oracle.jdbc.tokenAuthentication=OCI_TOKEN), as shown in the example.

Example: Assume one-way TLS is enabled, go to your Autonomous Database, click on 'DB Connection' and under 'Connection Strings' section, copy the connection URL by choosing "TLS" in the dropdown and append the connection property oracle.jdbc.tokenAuthentication=OCI_TOKEN to the URL. 

Connection URL:  jdbc:oracle:thin:@(description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.us-phoenix-1.oraclecloud.com))(connect_data=(service_name=xxxxxxxxxxxxxx_dbname_medium.adb.oraclecloud.com)))?oracle.jdbc.tokenAuthentication=OCI_TOKEN

Option 2: Alternatively, the IAM token-related property can be set as a connection property, as shown below.

Step 5: Verify through Java sample code

Download the JDBCDBTokenSample.java or UCPDBTokenSample.java code and update the DB_URL to point to your Autonomous Database. Ensure that you have retrieved the IAM database token using the command oci iam db-token get before running your sample. Compile and run these samples. The output should look as shown below. 

Step 6: Use token-based authentication with connection pooling

Because the IAM database tokens are relatively short-lived (1 hour), they need to be periodically refreshed if used in a long-lived application that uses a connection pool. Use the Oracle JDBC driver’s OracleCommonDataSource and configure a Supplier of such tokens using the setTokenSupplier method. This supplier uses the OCI-SDK for Java to retrieve database tokens programmatically. To complete the picture, the driver offers a token cache to optimize the frequency of the token refreshes by using its expiry time, and UCP also extends to support a token Supplier.

Find the complete code example here (see the method connectUcpDataSource).

References:

Nirmala Sundarappa

Principal Product Manager

My name is Nirmala Sundarappa. I am the Product Manager for Oracle Java Database Connectivity (JDBC) driver and Universal Connection Pool (UCP) used with Oracle Database. 

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. 

Michael McMahon

Java Developer

 Michael McMahon works on Oracle JDBC and Oracle R2DBC.


Previous Post

Debugging Oracle OKE using Rookout

Robert Ronan | 3 min read

Next Post


Lifting a Java EE application to Verrazzano

Rafael Benevides | 20 min read