Difficulty: Intermediate
TL;DR Problem: Enterprise users need SSO into an APEX app, but SAML callbacks are blocked on managed ORDS (HTTP 403 / ORDS-13002), so the obvious path dead-ends. Stack: Oracle APEX on Autonomous Database (ATP), Oracle-managed ORDS, Microsoft Entra ID (Azure AD), OpenID Connect. Who should read: Anyone wiring a customer-facing or internal APEX app to corporate identity on a managed ATP instance — especially after hitting the SAML 403 wall.
Tested on: Oracle APEX 24.2.17, ORDS Oracle-managed on Autonomous Database (ATP 26ai, Always Free), Microsoft Entra ID. Requires Entra admin (App registrations) and APEX Workspace admin. <!– WORDPRESS: insert a File block here (Add block → File). Upload APEX-Entra-OIDC-Login-Guide.pdf to Media, select it, enable “Show download button”. Suggested link text: “Download the full step-by-step guide (PDF)”. The line below is a placeholder for non-WordPress renders — delete it once the File block is in place. –>
We are building an APEX application on Autonomous Database to manage a customer’s subscription-related data. One requirement landed early: corporate single sign-on. Every authenticated employee should open the app with their existing Microsoft credentials, with a handful of privileged pages restricted to named administrators — no second password, no local account to provision, no help-desk ticket to onboard a user.
This post documents the login pattern as we proved it in the prototype on an Always Free ATP instance, ahead of rolling it into the customer’s solution. The instinctive route was SAML, because the organization already federated other apps that way. On a managed Autonomous Database that route fails. ORDS is Oracle-managed, so you cannot set security.externalSessionTrustedOrigins. SAML’s callback is a cross-origin POST, and ORDS blocks it with HTTP 403 / ORDS-13002. Per Oracle’s documentation, SAML Sign-In on Autonomous Database is supported only with a customer-managed ORDS — which means standing up and maintaining your own ORDS tier just to log in.
We didn’t want that operational burden, so we built OIDC instead. OIDC uses a redirect-based authorization-code flow that never triggers the cross-origin block, so it works on the default managed ORDS with nothing extra to run. We proved out two variants: a direct path (APEX → OIDC → Entra) and a brokered path (APEX → OIDC → OCI Identity Domain → SAML → Entra) for the case where one identity hub should front several IdPs.
SAML on managed ATP is a dead end unless you take over ORDS. OIDC’s authorization-code redirect flow sidesteps the cross-origin block entirely, so “Log in with Microsoft” works on the stock managed instance — choose SAML only when it’s a hard organizational mandate, and then budget for customer-managed ORDS.
In the Entra admin center, go to App registrations → New registration. Name it (e.g. APEX OIDC Login), pick single-tenant, and set the Redirect URI as platform Web:
https://<host>.adb.<region>.oraclecloudapps.com/ords/apex_authentication.callback
APEX uses a single OAuth/OIDC callback of the form https://<host>/ords/apex_authentication.callback. From the registration Overview, copy the Application (client) ID (not the Object ID, not the tenant ID) and the Directory (tenant) ID.
Under Certificates & secrets → New client secret, set an expiry and copy the secret Value immediately — it is shown only once. Record the expiry date; you will rotate against it.
Under API permissions, ensure delegated Microsoft Graph openid, profile, and email are present and admin-consented.
APEX needs only the discovery endpoint; it reads authorize, token, userinfo, and JWKS from it automatically:
https://login.microsoftonline.com/<tenant-guid>/v2.0/.well-known/openid-configuration
Open it in a browser to confirm it returns JSON.
Social Sign-In makes outbound calls from the database to Microsoft, so the parsing schema must be allowed to reach the Microsoft endpoints. On our Always Free ATP instance this was already in place — we did not have to make any ACL change, and login worked without touching DBMS_NETWORK_ACL_ADMIN. Your instance may differ depending on its network egress configuration, so test login first and only add an ACL if it fails.
The symptom that tells you an ACL is missing: login dies with ORA-24247 network access denied. If you hit that, grant the parsing schema connect privilege to login.microsoftonline.com and graph.microsoft.com. On Autonomous Database, appending to the ACL is done as ADMIN, and the exact call varies by release — verify against current Oracle docs before running it.
Then raise the web-service request limit: INTERNAL workspace → Manage Instance → Security → Workspace Isolation → Maximum Web Service Requests.
In App Builder → Workspace Utilities → Web Credentials, click Create:
| Field | Value |
|---|---|
| Name | Azure OIDC |
| Authentication Type | OAuth2 Client Credentials Flow |
| Client ID or Username | Application (client) ID |
| Client Secret or Password | Secret Value |
| Valid for URLs | https://login.microsoftonline.com |
The secret is stored encrypted. Note that updating “Valid for URLs” later forces you to re-enter the secret.
Open the app → Shared Components → Authentication Schemes → Create → Based on a pre-configured scheme from the gallery, Scheme Type Social Sign-In:
| Field | Value |
|---|---|
| Name | Azure AD OIDC |
| Credential Store | Azure OIDC |
| Authentication Provider | OpenID Connect Provider |
| Discovery URL | .../v2.0/.well-known/openid-configuration |
| Scope | openid email profile |
| Username Attribute | preferred_username |
| Convert Username To Upper Case | Yes (if roles are stored uppercase) |
| Verify Attributes | Yes |
Set Username to #preferred_username#. This is the single most important field on the page, and the reason is in the Gotchas below.
Making a scheme Current routes all app login through Entra. If it’s misconfigured you cannot fall back from the runtime app. Do it in this order:
Authentication (who the user is) is Entra’s job; authorization (what they may do) is Application Access Control, and the two are independent.
Layer 1 — app entry. In Shared Components → Application Access Control → Configure Access Control, set “Any authenticated user may access this application” to Yes. Any successfully authenticated user can open the app without being listed — this removes the “Access denied by Application security check” wall.

Layer 2 — privileged pages. Define roles (e.g. ADMINISTRATOR, CONTRIBUTOR, READER). APEX auto-creates a matching Authorization Scheme per role; attach it to the page, region, button, or process you want to gate, and grant the role only to the few users who need it. Everyone else gets the default read-only experience.
This avoids per-login role provisioning: most users need no role at all, only elevated users get one, and the access list stays small and meaningful.
Instead of APEX speaking OIDC directly to Entra, APEX can speak OIDC to an OCI Identity Domain, which federates authentication to Entra via SAML. The user still signs in at Azure; APEX only ever speaks OIDC to OCI. We proved this variant alongside the direct path, for the case where one identity hub should front multiple IdPs or where the same domain already fronts the customer’s Fusion pod.
Create a Confidential Application in the domain (OCI Console → Identity & Security → Domains → Integrated applications → Add application), grant type Authorization Code, Redirect URL = the same APEX callback. Activate it, copy its Client ID and Client Secret, and note its discovery URL:
https://<domain-id>.identity.oraclecloud.com/.well-known/openid-configuration
In APEX, build a second Web Credential (OCI OIDC) and Social Sign-In scheme against that discovery URL. Two differences from the direct path matter, both found during testing — see Gotchas.
preferred_username, never email, as the Username Attribute (direct Entra path). Entra users without a mailbox have no email claim, which produces “Null username passed to login procedure” for exactly those users. preferred_username (the UPN) is populated for every user. Don’t use #sub# either — it’s an opaque GUID that won’t match your ACL grants.user_domain.com#EXT#@tenant.onmicrosoft.com. That UPN is the value the token returns, so any role grants must use that exact string.#sub# instead. IDCS-style OCI domains advertise only a minimal base claim set (aud, exp, iat, iss, jti, sub) — no guaranteed preferred_username/email in discovery — so #sub# is the safe choice. Confirm what #sub# resolves to on first login and key your role grants to that.openid in the Scope field. APEX adds openid automatically. If you also set it, the request sends openid openid profile email and the domain rejects it with invalid_request / “duplicate values.” Set Scope to profile email and let APEX add openid. (Hit and resolved during testing.)APEX_UTIL.CREATE_USER. With Social Sign-In the IdP authenticates the user; we confirmed login still works after deleting the local account.AADSTS50011 redirect_uri mismatch means the URI APEX sent isn’t registered. Copy the exact URI from the Microsoft error page into App Registration → Authentication → Redirect URIs verbatim.invalid_client / AADSTS7000215). Rotate before expiry — see below.Entra allows two valid secrets on one registration at once, so rotation is outage-free:
The brokered OCI path generally avoids this clock: the secret APEX holds is the OCI confidential-app secret, which is usually long-lived. Confirm its expiry in your OCI Console rather than assuming — whatever you find there determines whether forced rotation applies to this path at all.
ORA-24247 network access denied at login → the parsing schema can’t reach the Microsoft endpoints; add the ACL (Section 2). On our Always Free instance this wasn’t needed, but yours may require it.Access denied by Application security check → authentication succeeded, authorization didn’t. Either set “Any authenticated user may access” = Yes, or grant the user a role.sub or the wrong claim on the direct path; switch to preferred_username.OIDC Social Sign-In gives an APEX app on managed ATP real corporate SSO without taking over ORDS and without provisioning a single local account. Entra owns identity, Application Access Control owns authorization, and onboarding a new user becomes a no-op. The brokered OCI variant adds an identity hub when you need to federate several IdPs or share one source with Fusion.
Facing the SAML-on-managed-ORDS wall, or wiring an APEX app to Entra and unsure whether to go direct or broker through OCI? We’ve built and proven both patterns end to end, and we can implement them in your environment. Reach out at info@cidsolutions.co.il or WhatsApp — let’s get it solved.
Tags: Oracle APEX, Autonomous Database, ATP, OIDC, Microsoft Entra ID, Azure AD, Single Sign-On, ORDS, OCI Identity Domain, Social Sign-In
Related posts: (first APEX post — no prior chain link yet. Forward-links to add as the APEX chain grows: OAuth setup for REST Data Sources, and REST Data Source Synchronization caching.)