OCI Authentication in Helidon
OCI Authentication in Helidon
How Helidon 4.4.0 discovers and exposes OCI BasicAuthenticationDetailsProvider instances.
If you use the OCI Java SDK
directly, sooner or later you need a
BasicAuthenticationDetailsProvider.
That is the object OCI SDK clients use for request signing,
tenant and user identification, session tokens, or workload identity.
Helidon 4.4.0 has dedicated OCI integration in integrations/oci that turns this into framework
plumbing instead of application boilerplate. Instead of manually building the authentication provider
in each application, Helidon can discover one, expose it through Service Registry, and let the rest
of the application inject it.
This post walks through the supported authentication variants, which ones need extra modules, and how to consume the resulting provider in Helidon SE and MP applications.
- Where OCI auth lives in Helidon 4.4
- Base module and configuration sources
- Built-in authentication methods
- Principal-based methods and extra dependencies
- Automatic selection and explicit selection
- Injecting BasicAuthenticationDetailsProvider
- Conclusion
Where OCI auth lives in Helidon 4.4
There are currently three relevant pieces in Helidon 4.4.0:
io.helidon.integrations.oci:helidon-integrations-oci- ⚠️
io.helidon.integrations.oci.sdk:helidon-integrations-oci-sdk-runtime - ⚠️
io.helidon.integrations.oci.sdk:helidon-integrations-oci-sdk-cdi
The important one for new Helidon SE code is helidon-integrations-oci. It is the current Service
Registry based integration and it is the module this article focuses on.
⚠️ The older helidon-integrations-oci-sdk-runtime still exists, but it is deprecated since Helidon
4.1.0 and replaced by helidon-integrations-oci.
⚠️ In practice, I would treat helidon-integrations-oci-sdk-cdi as deprecated as well. For this
article I use helidon-integrations-oci as the current path and rely on the Helidon MP Service
Registry to CDI bridge when looking at @Inject BasicAuthenticationDetailsProvider.
Base module and configuration sources
The base dependency is straightforward:
<dependency>
<groupId>io.helidon.integrations.oci</groupId>
<artifactId>helidon-integrations-oci</artifactId>
<version>${helidon.version}</version>
</dependency>
Once this module is on the classpath, Helidon can publish
com.oracle.bmc.auth.BasicAuthenticationDetailsProvider through Service Registry.
One detail is worth keeping in mind from the start: there are two different configuration worlds.
oci-config.yamlis Helidon configuration, typically using thehelidon.oci.*prefix.~/.oci/configis the standard OCI SDK configuration file.
That distinction matters because some methods are driven by oci-config.yaml, some by ~/.oci/config,
and session-token can work with either.
The Helidon OCI module reads its configuration from:
- environment variables
- system properties
oci-config.yamlon the filesystemoci-config.yamlon the classpath
For oci-config.yaml itself, the default lookup is very literal:
- on the filesystem, Helidon looks for
./oci-config.yaml, which meansoci-config.yamlin the current working directory - on the classpath, Helidon looks for a resource named
oci-config.yaml, which in a typical application meanssrc/main/resources/oci-config.yaml
If oci-config.yaml is not present, Helidon does not fail just because of that. With the default
authentication-method: auto, it can still discover credentials from environment variables, system
properties, and the standard OCI SDK configuration file such as
~/.oci/config.
A minimal starting point looks like this:
helidon.oci:
authentication-method: auto
Built-in authentication methods
The base helidon-integrations-oci module supports three authentication methods out of the box:
| Method | Backing OCI SDK provider | Typical use |
|---|---|---|
config |
SimpleAuthenticationDetailsProvider |
Full application-managed configuration |
config-file |
ConfigFileAuthenticationDetailsProvider |
Local development or admin tooling using ~/.oci/config |
session-token |
SessionTokenAuthenticationDetailsProvider |
Temporary sessions and token-based flows |
Config
config is the most explicit option. All important values are provided through Helidon config, so
the application does not depend on an OCI config file being present.
helidon.oci:
authentication-method: config
authentication:
config:
region: eu-frankfurt-1
fingerprint: "20:3b:aa:bb:cc:dd"
tenant-id: "ocid1.tenancy.oc1..aaaa..."
user-id: "ocid1.user.oc1..aaaa..."
private-key:
resource-path: "keys/oci_api_key.pem"
passphrase: "${OCI_API_KEY_PASSPHRASE}"
This method is nice when you want the application to be fully self-contained. The private key can be
provided as a Helidon Resource, which means classpath resource, filesystem resource, base64 content,
or plain text content. If you omit the private key entirely, Helidon falls back to
~/.oci/oci_api_key.pem.
For the underlying OCI side of this setup, see Required Keys and OCIDs and the SimpleAuthenticationDetailsProvider JavaDoc.
You can select config explicitly as shown above, but auto can also reach it when
helidon.oci.authentication.config is present.
Config File
config-file delegates to the standard
OCI SDK and CLI configuration file.
helidon.oci:
authentication-method: config-file
authentication:
config-file:
profile: DEFAULT
path: "/home/app/.oci/config"
If path is omitted, the OCI SDK default lookup is used. This is usually the best choice for local
development, developer laptops, bastion hosts, or scripts running with a conventional ~/.oci/config
layout.
This can also be used through auto. If Helidon finds a usable OCI config file and no higher-priority
method wins first, it can resolve config-file without forcing authentication-method.
The related OCI SDK type is ConfigFileAuthenticationDetailsProvider.
Session Token
session-token uses
SessionTokenAuthenticationDetailsProvider.
Helidon enables it in two ways:
- you configure
helidon.oci.authentication.session-token - or the OCI config file contains
security_token_file
An explicit oci-config.yaml setup can look like this:
helidon.oci:
authentication-method: session-token
authentication:
session-token:
region: eu-frankfurt-1
fingerprint: "20:3b:aa:bb:cc:dd"
tenant-id: "ocid1.tenancy.oc1..aaaa..."
user-id: "ocid1.user.oc1..aaaa..."
private-key-path: "/home/app/.oci/sessions/DEFAULT/oci_api_key.pem"
session-token-path: "/home/app/.oci/sessions/DEFAULT/token"
session-lifetime-hours: 8
refresh-period: PT55M
This method is useful when you want short-lived credentials instead of a long-lived API signing key.
If you already have a normal OCI config file with security_token_file, Helidon can build the
provider from that as well.
The OCI configuration file format for token-based sessions is described in the SDK and CLI Configuration File documentation.
Again, explicit selection is optional. auto can reach session-token too, either from
helidon.oci.authentication.session-token or from an OCI config file that contains
security_token_file.
Principal-based methods and extra dependencies
The principal-based variants are intentionally split into extra modules. The base
helidon-integrations-oci module does not force all of them on every application.
| Method | Extra artifact | Availability check |
|---|---|---|
instance-principal |
helidon-integrations-oci-authentication-instance |
OCI instance metadata service must be reachable |
resource-principal |
helidon-integrations-oci-authentication-resource |
OCI_RESOURCE_PRINCIPAL_VERSION must be set |
oke-workload-identity |
helidon-integrations-oci-authentication-oke-workload |
OKE service account CA certificate file must exist |
Instance Principal
For Compute instances running on OCI, add:
<dependency>
<groupId>io.helidon.integrations.oci.authentication</groupId>
<artifactId>helidon-integrations-oci-authentication-instance</artifactId>
<version>${helidon.version}</version>
</dependency>
You can select it explicitly, but auto can also reach it when the module is present and the OCI
instance metadata service is available:
helidon.oci:
authentication-method: instance-principal
This provider becomes available only when Helidon can reach OCI Instance Metadata Service. In other words, putting the dependency on the classpath is necessary, but not sufficient. The code still checks that it is actually running in an OCI instance environment.
On the OCI side, the best background reading is Calling Services from an Instance and the InstancePrincipalsAuthenticationDetailsProvider JavaDoc.
Resource Principal
For OCI Functions and similar resource-principal environments, add:
<dependency>
<groupId>io.helidon.integrations.oci.authentication</groupId>
<artifactId>helidon-integrations-oci-authentication-resource</artifactId>
<version>${helidon.version}</version>
</dependency>
And configure:
helidon.oci:
authentication-method: resource-principal
At runtime, Helidon checks for OCI_RESOURCE_PRINCIPAL_VERSION. If that environment variable is not
present, this method is considered unavailable and will not produce a provider.
auto can also reach this method. The explicit setting is only needed if you want strict,
fail-fast selection instead of discovery.
For the OCI side of the setup, see Accessing Other Oracle Cloud Infrastructure Resources from Running Functions and the ResourcePrincipalAuthenticationDetailsProvider JavaDoc.
OKE workload identity
For workloads running on OKE, add:
<dependency>
<groupId>io.helidon.integrations.oci.authentication</groupId>
<artifactId>helidon-integrations-oci-authentication-oke-workload</artifactId>
<version>${helidon.version}</version>
</dependency>
And configure:
helidon.oci:
authentication-method: oke-workload-identity
This module is slightly different from the other two. Under the hood it also pulls the OCI SDK addon for OKE workload identity, so you do not have to wire that dependency separately in your application.
Availability is detected through the Kubernetes service account CA certificate path. Helidon checks
OCI_KUBERNETES_SERVICE_ACCOUNT_CERT_PATH first and otherwise falls back to
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt.
This one is reachable through auto as well, provided the module is present and the workload identity
environment is actually available.
The OCI platform side is documented in Granting Workloads Access to OCI Resources.
Shared tuning for principal-based providers
Instance principal, resource principal, and OKE workload identity all reuse the common helidon.oci
settings below:
helidon.oci:
authentication-timeout: PT10S
imds-detect-retries: 3
federation-endpoint: "https://auth.eu-frankfurt-1.oraclecloud.com/"
imds-base-uri: "http://169.254.169.254/opc/v2/"
tenant-id: "ocid1.tenancy.oc1..aaaa..."
You normally do not need all of them, but it is good to know that the principal-based builder providers share this customization surface.
Automatic selection and explicit selection
By default, Helidon uses:
helidon.oci:
authentication-method: auto
With auto, Helidon tries the available authentication methods and uses the first one that can
actually build a BasicAuthenticationDetailsProvider.
In practice, the built-in ordering in Helidon 4.4 looks like this:
configsession-tokenconfig-fileresource-principalinstance-principaloke-workload-identity
This is convenient when you want the same application to work on a laptop and then in OCI, but when
the deployment target is known, I usually prefer an explicit authentication-method. It removes
guessing and makes failures much easier to understand.
Explicit selection is also strict by design. If you choose instance-principal,
resource-principal, or any other concrete method and that provider cannot be created in the current
environment, Helidon fails instead of silently falling back to something else.
⚠️ One more detail: if you read older OCI CDI examples or older internals in the Helidon source tree, the
strategy names are not completely identical. The current Service Registry based integration uses names
such as instance-principal and session-token, while the older legacy CDI strategy layer still
refers to things like instance-principals, session-token-builder, and
session-token-config-file. That does not change how the new module works, but it is useful context
when comparing examples across generations of the integration.
Injecting BasicAuthenticationDetailsProvider
Once Helidon has resolved the authentication method, the useful part begins: the resulting
BasicAuthenticationDetailsProvider can be injected and reused across OCI SDK clients.
Helidon SE constructor injection
With the current Service Registry based integration, the cleanest option is constructor injection:
import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
import com.oracle.bmc.objectstorage.ObjectStorageClient;
import io.helidon.service.registry.Service;
@Service.Singleton
class BucketService {
private final BasicAuthenticationDetailsProvider auth;
@Service.Inject
BucketService(BasicAuthenticationDetailsProvider auth) {
this.auth = auth;
}
ObjectStorageClient client() {
return ObjectStorageClient.builder().build(auth);
}
}
That keeps OCI authentication discovery in the framework layer and leaves your application code with a simple dependency on the provider contract.
Static lookup with Services.get(…)
For code that is not itself a managed service, Helidon also exposes the provider through static Service Registry lookup:
import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
import io.helidon.service.registry.Services;
BasicAuthenticationDetailsProvider auth =
Services.get(BasicAuthenticationDetailsProvider.class);
That is handy in main methods, integration bridges, or migration code. In normal declarative SE
services I still prefer constructor injection, but Services.get(...) is perfectly valid when you
need an escape hatch.
Helidon MP CDI injection
For Helidon MP, the recommended path is also helidon-integrations-oci. Helidon MP includes a
general Service Registry to CDI bridge, so the resolved BasicAuthenticationDetailsProvider can be
injected as a CDI bean without adding the older OCI-specific CDI module:
import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@ApplicationScoped
public class BucketService {
@Inject
BasicAuthenticationDetailsProvider auth;
}
⚠️ Treat helidon-integrations-oci-sdk-cdi as the legacy OCI SDK CDI path. It may still matter if
you rely on its broader OCI SDK client and builder injection support, but for
BasicAuthenticationDetailsProvider itself the current article uses helidon-integrations-oci and
the MP CDI bridge.
Conclusion
Helidon 4.4.0 gives OCI authentication a clean, modular shape:
config,config-file, andsession-tokenare available directly fromhelidon-integrations-ociinstance-principal,resource-principal, andoke-workload-identityare opt-in add-ons- ⚠️
helidon-integrations-oci-sdk-runtimeandhelidon-integrations-oci-sdk-cdishould be treated as legacy paths - once resolved, the provider is available as
BasicAuthenticationDetailsProvider
For local development, config-file is usually the easiest start. For application-owned secrets,
config keeps everything under Helidon control. For OCI-native deployments, use the matching
principal-based module and set authentication-method explicitly.
The nice part is what happens afterwards: your code no longer cares how authentication was discovered.
It just injects BasicAuthenticationDetailsProvider in SE or MP, or looks it up with Services.get
when needed.