Skip to content

CID Software Solutions LTD

Home » APEX on ATP: Add “Log in with Microsoft” by using Entra ID OIDC Social Sign-In

APEX on ATP: Add “Log in with Microsoft” by using Entra ID OIDC Social Sign-In

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

Business Challenge

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.

Why OIDC, not SAML

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.

Solution Overview

  1. Register an App Registration in Entra (this is a different object from a SAML “Enterprise Application” — don’t reuse one).
  2. Capture the Application (client) ID and Directory (tenant) ID, and create a client secret.
  3. Grant the APEX schema a network ACL out to the Microsoft endpoints.
  4. Create an APEX Web Credential holding the client ID and secret.
  5. Create a Social Sign-In authentication scheme pointed at Entra’s discovery URL.
  6. Gate the app with Application Access Control — open entry to any authenticated user, role-gate the privileged pages.
  7. (Optional) Broker through an OCI Identity Domain instead of talking to Entra directly.

Implementation Details

1. Entra App Registration

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.

2. Network ACL — check before you assume you need it

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.

3. APEX Web Credential

In App Builder → Workspace Utilities → Web Credentials, click Create:

FieldValue
NameAzure OIDC
Authentication TypeOAuth2 Client Credentials Flow
Client ID or UsernameApplication (client) ID
Client Secret or PasswordSecret Value
Valid for URLshttps://login.microsoftonline.com

The secret is stored encrypted. Note that updating “Valid for URLs” later forces you to re-enter the secret.

4. Social Sign-In Scheme

Open the app → Shared Components → Authentication Schemes → Create → Based on a pre-configured scheme from the gallery, Scheme Type Social Sign-In:

FieldValue
NameAzure AD OIDC
Credential StoreAzure OIDC
Authentication ProviderOpenID Connect Provider
Discovery URL.../v2.0/.well-known/openid-configuration
Scopeopenid email profile
Username Attributepreferred_username
Convert Username To Upper CaseYes (if roles are stored uppercase)
Verify AttributesYes

Set Username to #preferred_username#. This is the single most important field on the page, and the reason is in the Gotchas below.

5. Activate safely (don’t lock yourself out)

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:

  1. Keep your App Builder session open in the current browser — that is your revert path.
  2. Make Azure AD OIDC the Current scheme.
  3. In a separate incognito window, open the app home URL.
  4. Expected: redirect to Microsoft → authenticate → first-time consent → redirect back, logged in.
  5. If it fails, return to the still-open App Builder session and set the scheme back to Oracle APEX Accounts.

6. Authorization — open entry, role-gate the rest

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.

APEX Entra ID OIDC login — Configure Access Control dialog with "Any authenticated user may access this application" set to Yes, and Administrator / Reader / Contributor roles listed

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.

Alternative: broker through an OCI Identity Domain

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.

Gotchas / Production notes

  • Use 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.
  • Guest/external users surface as user_domain.com#EXT#@tenant.onmicrosoft.com. That UPN is the value the token returns, so any role grants must use that exact string.
  • On the brokered OCI path, use #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.
  • Brokered path: do NOT put 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.)
  • No local APEX account is needed. Don’t create accounts via 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.
  • Entra secrets expire and take all logins down with them. When the secret lapses every login fails at the token step (invalid_client / AADSTS7000215). Rotate before expiry — see below.

Client-secret rotation (zero downtime)

Entra allows two valid secrets on one registration at once, so rotation is outage-free:

  1. Create a new secret in Entra (new expiry, copy the Value immediately).
  2. Paste it into the APEX Azure OIDC Web Credential (Client Secret + Verify), Apply. The Client ID is unchanged.
  3. Test in an incognito window.
  4. Delete the old secret in Entra so a leaked old value can’t be used.
  5. Record the new expiry and set a reminder 2–4 weeks ahead.

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.

How to verify

  • Login round-trip: in incognito, open the app home URL; you should bounce to Microsoft, authenticate, and land back inside the app.
  • 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.
  • Username is a GUID or blank → Username Attribute is set to sub or the wrong claim on the direct path; switch to preferred_username.
  • All logins fail at the token step → expired/wrong client secret; rotate.

Conclusion

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.

Get this into your environment

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

Leave a Reply

Your email address will not be published. Required fields are marked *