Difficulty: Advanced
Series — Passwordless Fusion integration (part 3) Earlier: Fusion Apps: Call OIC Synchronously as the Real User by using a Native IDCS OAuth Connection (Jul 2026) · Fusion OTBI: Securely obtain a session ID from OIC by using OCI Vault and an Oracle Function (May 2026)
Problem: You can build an OIC estate with no stored passwords — right up to the point where you need BI Publisher. The Oracle ERP Cloud adapter and every Fusion REST connection support JWT User Assertion and OAuth 2.0 Client Credentials, so those connections hold no password. BI Publisher’s report execution API is SOAP (ExternalReportWSSService), the native BIP REST endpoints return 404 in Fusion, and the stock SOAP adapter’s authentication is WS-Security UsernameToken. So one connection in your instance ends up storing a Fusion username and password — and it is usually the one with the widest reach, because reporting touches everything.
What we found: Fusion accepts an OAuth 2.0 bearer token on the BI Publisher SOAP endpoints with no wsse:Security header at all. The password is a limitation of the adapter, not of the service.
Solution: We built CID Fusion BIP, a custom OIC adapter (Rapid Adapter Builder) that exposes both ExternalReportWSSService and ScheduleReportWSSService as typed JSON actions — 48 of them — and posts the SOAP envelope internally with a bearer token. Integration developers map ordinary JSON fields; nobody sees XML, and no connection stores a password.
Download: the adapter definition and setup guides are at the end of this post.
Tested on Fusion 26B · OIC Gen 3 (Gen 2 cannot host RAB adapters) · Fusion and OIC in the same OCI identity domain · an OCI IAM/IDCS Confidential Application allowing the jwt-bearer grant · a signing key uploaded to the OIC keystore with its certificate trusted in the Fusion identity domain · VS Code with the Oracle.oic-rapid-adapter-builder extension (v1.2.0) · an IAM application with the ServiceDeveloper role to register the bundle.
Status note, in the interest of not overselling this: runReport is proven end to end on a live instance — with and without parameters, single and multi-value parameters, PDF output decoding to a valid file, values containing &, < and >, business errors normalized, and reportBytes written to a stage file. The other 47 actions are generated from the instance WSDLs and verified offline (887 checks, including parsing every request envelope with an XML parser), but they have not each been exercised against Fusion. Treat the first live call to any of them as a test. Where that matters is called out below.
This is the third post in a chain about removing stored credentials from Fusion↔OIC integration. Part 1 brokered OTBI credentials through OCI Vault so they never appear in an OIC flow. Part 2 replaced a username/password BIP HTTP connection — and a hand-rolled OAuth hop — with a native IDCS OAuth connection, so the OIC log shows the real user. This post closes the remaining hole: the BIP connection in the other direction, OIC calling Fusion.
It is also worth reading alongside Groovy → ESS → BIP(HTTP) → OIC async offload, because that pattern is still the right answer for long-running reports. This adapter is for synchronous, bounded calls and for job control — it does not replace ESS-with-wait.
“No stored passwords” is not a purist position. A password in a connection is a credential nobody rotates, that survives a Production-to-Test clone, that appears in an audit as a shared service account, and that grants whatever that Fusion user can do — which for a reporting account is usually a great deal of data.
The state of play on Fusion connections in OIC:
| Connection | Passwordless option | Status |
|---|---|---|
| Oracle ERP Cloud adapter (REST) | JWT User Assertion, OAuth Client Credentials | Supported [Confirmed] |
| Fusion REST via the REST adapter | OAuth 2.0, JWT assertion | Supported [Confirmed] |
| Fusion SOAP via the SOAP adapter | — WS-Security UsernameToken | Not supported [Confirmed] |
| BI Publisher native REST | — endpoints return 404 in Fusion | Not available [Confirmed] |
So the design that is otherwise clean acquires one exception, and that exception is BI Publisher: ExternalReportWSSService.runReport is the supported synchronous path for running a report from OIC, and the stock route to it wants a username and password.
The usual workarounds are all worse than they look. Storing the password in the connection and “reviewing it later” means it is still there at the next P2T. Brokering it from OCI Vault at runtime — our own pattern P7 — protects the secret in transit and in logs but does not eliminate it; you still have a Fusion password, just better hidden. Wrapping BIP behind an OCI Function to do the auth adds a component, a deployment and a cold start to every report call.
Oracle Integration 3 ships the Rapid Adapter Builder (RAB): you describe a custom adapter in a JSON adapter definition document, build it into a .rab bundle from VS Code, and register it to an OIC instance, where it appears in Design → Adapters and can be used to create connections like any Oracle-supplied adapter.
The critical enabler is the finding above. We verified it outside OIC first, with a plain HTTP call carrying only Authorization: Bearer … and no wsse:Security header, against /xmlpserver/services/ExternalReportWSSService. Fusion returned the report. [Confirmed by testing]
That means a custom adapter can:
&, < and >, POST it, and extract the response back into named JSON fields.errorCode / errorMessage contract, so a business error is never a bare HTTP 500 and never passes as success.Coverage in 2.1.0, from the instance WSDLs rather than from documentation:
| Service | Path | Actions | Group in the wizard |
|---|---|---|---|
ExternalReportWSSService | /xmlpserver/services/ExternalReportWSSService | 29 | BI Publisher — Reports |
ScheduleReportWSSService | /xmlpserver/services/ScheduleReportWSSService | 19 | BI Publisher — Scheduling |
Reports covers execution, catalog access, templates and data chunks. Scheduling covers job submission, history, output retrieval, delivery info, and cancel/suspend/resume/resend.
An invoke, the connection, and an action list grouped by service. For a report:
{
"reportAbsolutePath": "/Custom/Project/Utils/TestReport.xdo",
"attributeFormat": "pdf",
"attributeLocale": "en-US",
"parameterNameValues": [
{ "name": "P_LEDGER", "values": ["Primary Ledger"] },
{ "name": "P_PERIOD", "values": ["AUG-26", "SEP-26"] }
]
}
and back:
{
"httpStatus": 200,
"reportBytes": "<base64>",
"reportContentType": "application/pdf",
"metaDataTag": "",
"errorCode": "",
"errorMessage": ""
}
No envelope, no namespaces, no wsse header, no password. Multi-value parameters work; values containing &, < or > are escaped by the adapter, so there is nothing to pre-encode.
reportBytes is base64 exactly as BIP returned it. Map it through the mapper’s base64-decode into a Stage File → Write File and use the staged file reference downstream. Do not decode a PDF or XLSX into a string variable — that corrupts it by construction.
Both are the kind of thing that produces a well-formed envelope which Fusion rejects, and neither is visible in any structural validation.
elementFormDefault differs between the two services. ExternalReportWSSService is qualified — every child element carries the namespace prefix. ScheduleReportWSSService is unqualified — only the operation element is prefixed and the children are bare:
<!-- ExternalReportWSSService: children prefixed -->
<pub:isReportExist><pub:reportAbsolutePath>/Custom/…</pub:reportAbsolutePath></pub:isReportExist>
<!-- ScheduleReportWSSService: children bare -->
<sch:getReportHistoryInfo><jobInstanceID>12345</jobInstanceID></sch:getReportHistoryInfo>
Get it backwards and every call to that service fails while the other works perfectly.
Both services are SOAP 1.2. Envelope namespace http://www.w3.org/2003/05/soap-envelope, Content-Type: application/soap+xml. A SOAP 1.1 envelope with text/xml is refused. We lost time here because a SOAP fault came back gzipped and read as a small binary body that looked like a successful document. If you test a BIP endpoint with curl, always use curl --compressed.
Full detail is in INSTALL.md in the download; the shape of it:
Cmd+Shift+P → RAB: Initialize Workspace in an empty folder, then copy the downloaded .add.json over the definitions/main.add.json the initializer created.publisherId, host, integrationInstance, and auth for an IAM application with the ServiceDeveloper role. On macOS this file lives under $TMPDIR, which is periodically purged — keep the values somewhere durable.Bundles are per OIC instance and are not carried by integration or configuration-set export. DEV, TEST and PROD are three separate registrations, and this belongs in your P2T runbook next to connection re-creation. A missing bundle in TEST presents as an integration that cannot be activated — a confusing symptom if nobody wrote the step down.
Design → Connections → Create → CID Fusion BIP.
| Field | Value |
|---|---|
| Fusion Base URL | the Fusion host; a trailing slash is tolerated |
| Assertion Issuer (iss) | client id of the IDCS Confidential Application |
| Assertion Subject (sub) | a real Fusion username — the identity every report runs as |
| Assertion Audience (aud) | e.g. https://identity.oraclecloud.com/ |
| Signing Key Alias (kid) | alias of the signing key in the OIC keystore |
| Security policy | OAuth using JWT User Assertion |
| Access Token URI | the identity domain’s token endpoint |
| JWT Private Key Alias | the same alias |
| Scope | as on a working Fusion/ERP Cloud connection |
The signing key must be in that instance’s keystore and its certificate trusted in that identity domain — both are per environment. The IDCS application must allow the jwt-bearer grant, and ideally authenticate the client with client_assertion; if it insists on Basic, an access-token-request override is needed, which stores a client secret in a string property. That is fine for a proof of concept and not fine beyond it — fix the IDCS application instead.
sub before anyone builds against the connectionEvery call through one connection runs as that one Fusion user, and the adapter exposes catalog and job administration alongside execution — deleteReport, deleteFolder, purgeJobHistory, updateReportDefinition, the upload family. Fusion privileges on the asserted user are the only control. The adapter enforces nothing, and the identity is shared by every consumer of the connection.
Our recommendation: give the shared connection a read/execute-only BI Publisher identity, and provision a second connection with an authoring identity only in the environment and for the flow that genuinely needs to write. Two connections, not two adapters — the adapter is identity-agnostic.
reportBytes is populated.Step 2 is not optional, and this is the gotcha we would most like to save you: OIC caches the access token per connection. A green connection test can be reusing a token minted by a configuration you have since changed. We spent an hour convinced an auth change worked because the test was green; it was serving a cached token from a previous attempt. A connection test is not evidence that authentication works.
If you plan to use actions beyond runReport, start with Is Report Exist (smallest possible envelope, proves the Reports path) and one Scheduling action such as Get Report History Info (proves the bare child-element qualification). Those two passing validates the riskiest assumption for the whole set.
sizeOfDataChunkDownload is exposed but the whole document returns in one response. Measure the practical size ceiling in your environment before relying on it for large outputs.scheduleReport is untested at size. Its 114 mappable fields compile to a single 32 KB expression. It is well-formed and correct offline, but whether the runtime expression engine accepts something that large is genuinely unknown. If you need scheduling with exotic delivery channels, prove that action early.[cid-fusion-bip-2.1.0.zip] — contains:
cid-fusion-bip-2.1.0.add.json — the adapter definition document, 48 actionsINSTALL.md — prerequisites through to a verified connectionUSAGE.md — for the integration developers who will consume itOPERATION_INVENTORY.md — every action, its input size, the caveats, the governance notesCHANGELOG.md — version history and the rule class of each changeThe definition contains no hostnames, no identity-domain ids, no keys and no customer references — every environment-specific value is a connection property you supply, which is what makes it P2T-safe. Provided as-is; test it in a non-production environment first.
The password in your BI Publisher connection is not a Fusion constraint. Fusion has accepted a bearer token on those SOAP endpoints all along; what was missing was an adapter willing to send one. A Rapid Adapter Builder wrapper supplies that, and while it is doing so it can also remove SOAP from the developer experience entirely — 48 operations across both BI Publisher services become typed JSON in a mapper, with one uniform error contract and no envelope anywhere in an integration.
The wider point is about where the exception lives. Before this, a passwordless OIC estate had one documented exception that everybody worked around individually. Now it has a component, in one place, that someone owns — and “no stored passwords” becomes a rule you can actually enforce in a design review rather than an aspiration with a footnote.
Sitting on a BI Publisher connection with a stored Fusion password, and not keen on an OCI Function in the middle of every report call? We proved the bearer-token path end to end, built the adapter, and can register it in your DEV/TEST/PROD instances and wire the IDCS trust, the signing keys and the connection identity correctly — including the part most people get wrong, which is deciding which Fusion user your reporting connection asserts. Reach out at info@cidsolutions.co.il or WhatsApp — let’s get it solved.