sapui5tutors SAPUI5 • Fiori • SAP BTP Step-by-step tutorials Real project examples Interview Q&A
Practical SAPUI5 • Fiori • SAP BTP tutorials and interview prep

SAP BTP Destinations: Connecting to S/4HANA

What a destination actually is

Almost every SAP BTP app that talks to S/4HANA goes through a destination. Think of it as a named address card: the URL, the authentication method, and the connection rules — stored once, reused everywhere.

Instead of hardcoding S/4HANA credentials in your CAP service or UI5 app (please don't), you create a destination like S4HANA_CLOUD in your subaccount. Your code only knows the name. The runtime resolves everything else.

Destinations decouple your code from connection details. Change the password, switch the system, move to production — and your app doesn't change at all.


Cloud Connector: the tunnel for on-premise

Connecting to a cloud S/4HANA (S/4HANA Cloud) is straightforward — it's reachable over the internet. Connecting to an on-premise system is the interesting case, because the on-premise system lives behind a corporate firewall.

That's what the Cloud Connector is for. It's a small agent you install inside the corporate network. It opens an outbound TLS tunnel to your BTP subaccount (so no firewall holes), and the Connectivity service uses it as a proxy for on-premise destinations.

Say you need to call an OData service on your on-premise S/4HANA from a CAP app in BTP. The flow is: CAP app → destination (with ProxyType: OnPremise) → Connectivity service → Cloud Connector → your S/4HANA system. You configure the mapping once in the connector; the app just calls the destination name.


The authentication choices that matter

The Authentication property of a destination is where most people get stuck. Here are the options you'll actually use:

  • NoAuthentication — anonymous. Fine for public sandbox APIs, nothing else.
  • BasicAuthentication — a technical user and password. Simple, common for system-to-system integration, but you own the password lifecycle.
  • OAuth2ClientCredentials — the app authenticates as itself with a client ID/secret. The clean choice for background integrations.
  • OAuth2UserTokenExchange — the app passes along the logged-in user's token (via XSUAA) to the backend. This is principal propagation: the S/4HANA system sees the actual end user, so authorizations apply per person.

Rule of thumb: background jobs get client credentials; anything a human clicks through gets user token exchange. A Fiori app showing sales orders should propagate the user, so the S/4HANA authorization concept stays in charge.

Principal propagation means the S/4HANA backend applies the real user's roles. Without it, everyone behind your app shares one technical user — and audit will notice.


Creating the destination

In the BTP cockpit, go to your subaccount → Connectivity → Destinations → New Destination. The typical S/4HANA entry looks like this:

  • Name: S4HANA_CLOUD
  • Type: HTTP
  • URL: your system's OData root, e.g. https://myXXXXXX.s4hana.cloud.sap/sap/opu/odata/sap/
  • Proxy Type: Internet (cloud) or OnPremise (via Cloud Connector)
  • Authentication: whichever you chose above, plus the client/secret or user credentials

Hit Check Connection. If it fails, it's almost always the URL trailing path, the auth credentials, or — for OnPremise — a missing Cloud Connector mapping.


Using it from a CAP service

In a Node.js CAP service, connecting is two lines. The destination is picked up by name at runtime:

const srv = await cds.connect.to('S4HANA_CLOUD')
const orders = await srv.get('/A_SalesOrder')
  .where({ SalesOrganization: '1710' })

No URL, no credentials in the code. In Java it's similar via the SAP Cloud SDK's destination accessor. The same destination can also back a UI5 app's OData model by referencing it in the app's router data source.

If you're wiring destinations into CAP, also read up on the XSUAA setup — principal propagation only works when your app and the backend share a trust relationship.


Common mistakes

  • Duplicating the same destination per app instead of sharing at subaccount level
  • Using BasicAuthentication everywhere because it's easy, then forgetting the password rotation
  • Forgetting ProxyType: OnPremise on Cloud Connector destinations — the error messages here are cryptic
  • Skipping the "Check Connection" step and debugging from the app side first

Get destinations right and every integration after them — CAP, UI5, Integration Suite — becomes boring in the best way.

Questions? Drop them in the comments.