| name | btp-destinations |
| description | Use when configuring SAP BTP Destination Service: creating destinations in BTP Cockpit, OAuth2ClientCredentials, OAuth2SAMLBearerAssertion, OAuth2JWTBearer, principal propagation, BasicAuthentication, Cloud Connector on-premise connectivity, reading destinations from CAP with cds.connect.to, or testing destinations locally with cds bind.
|
| metadata | {"category":"btp","version":"1.0.0","keywords":["Destination Service","OAuth2ClientCredentials","OAuth2JWTBearer","OAuth2SAMLBearerAssertion","principal propagation","BasicAuthentication","Cloud Connector","destination configuration"],"related":{"btp-service-bindings":"bind Destination Service locally","remote-services":"use destinations in CAP remote service config","btp-workzone":"destinations for Work Zone content federation"}} |
BTP Destinations — Best Practices
Primary reference: https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/destinations
Authentication methods: https://help.sap.com/docs/btp/btp-admin-guide/destination-authentication-methods
CAP + destinations: https://cap.cloud.sap/docs/guides/using-services#btp-destinations
Destinations are part of SAP BTP Connectivity and are used for communication between a cloud application and a remote system. They're resolved at runtime based on their symbolic names. For user token exchange, use the OAuth2JWTBearer authentication method when possible — OAuth2UserTokenExchange needs a two-step mechanism to achieve the same resolution. Avoid BasicAuthentication and OAuth2Password in production environments, though they work well for test environments.
Authentication types — when to use what
| Auth type | Use when |
|---|
NoAuthentication | Public APIs only |
BasicAuthentication | Dev/test only — never production |
OAuth2ClientCredentials | System-to-system, no user context needed |
OAuth2JWTBearer | User propagation, same subaccount (preferred over UserTokenExchange) |
OAuth2SAMLBearerAssertion | User propagation to on-premise or cross-subaccount |
OAuth2UserTokenExchange | User propagation — only if JWTBearer not available |
PrincipalPropagation | On-premise via Cloud Connector with user context |
OAuth2ClientCredentials — system-to-system
Configure in BTP Cockpit → Connectivity → Destinations:
Name: MY_API_DESTINATION
Type: HTTP
URL: https://api.example.com
ProxyType: Internet
Authentication: OAuth2ClientCredentials
clientId: <client-id>
clientSecret: <client-secret>
tokenServiceURL: https://auth.example.com/oauth/token
In CAP package.json:
{
"cds": {
"requires": {
"MyExternalAPI": {
"kind": "rest",
"credentials": {
"destination": "MY_API_DESTINATION",
"requestTimeout": 30000
}
}
}
}
}
OAuth2JWTBearer — user propagation (preferred)
Cloud to Cloud principal propagation: the user is propagated from a cloud application to another remote cloud system using a destination configuration with authentication types OAuth2SAMLBearerAssertion or OAuth2JWTBearer.
Name: S4HANA_CLOUD
Type: HTTP
URL: https://my.s4.example.com
Authentication: OAuth2JWTBearer
clientId: <client-id>
clientSecret: <client-secret>
tokenServiceURL: https://my-tenant.authentication.eu10.hana.ondemand.com/oauth/token
On-premise via Cloud Connector
Name: MY_ONPREMISE_SYSTEM
Type: HTTP
URL: http://virtualhost:port
ProxyType: OnPremise
Authentication: PrincipalPropagation
Requires the Cloud Connector to have:
- The virtual host mapped to the real backend
- The subaccount connected to BTP
- The correct SNC configuration for SAP systems
In mta.yaml — bind both Destination Service and Connectivity Service:
- name: my-app-srv
requires:
- name: my-app-destination
- name: my-app-connectivity ← required for on-premise!
- name: my-app-connectivity
type: org.cloudfoundry.managed-service
parameters:
service: connectivity
service-plan: lite
Reading destinations in CAP
CAP reads destinations automatically when a service uses credentials.destination:
const S4 = await cds.connect.to('S4HANA_CLOUD')
const result = await S4.run(SELECT.from('A_BusinessPartner'))
For manual access using the Destination Service REST API:
const { getDestination } = require('@sap-cloud-sdk/connectivity')
const destination = await getDestination({ destinationName: 'MY_DESTINATION' })
console.log(destination.url, destination.authTokens)
Local testing with destinations
cds bind -2 my-app-destination
cds watch --profile hybrid
Or configure a local mock destination in package.json:
{
"cds": {
"requires": {
"MyExternalAPI": {
"[development]": {
"kind": "rest",
"credentials": {
"url": "https://sandbox.api.sap.com/my-api",
"headers": { "APIKey": "{{SAP_API_HUB_KEY}}" }
}
},
"[production]": {
"kind": "rest",
"credentials": { "destination": "MY_API_DESTINATION" }
}
}
}
}
}
Common mistakes to avoid
-
❌ Using BasicAuthentication in production destinations
-
✅ Use OAuth2ClientCredentials for system-to-system, OAuth2JWTBearer for user propagation
-
❌ Forgetting the connectivity service binding for on-premise destinations
-
✅ On-premise always needs both destination and connectivity services in mta.yaml
-
❌ Hardcoding destination credentials in package.json
-
✅ Use [development] profile for local mocks, [production] for real destinations
-
❌ Using OAuth2UserTokenExchange when OAuth2JWTBearer is available
-
✅ OAuth2JWTBearer is preferred — it achieves the same result in one step
-
❌ Testing principal propagation with BasicAuthentication during development
-
✅ Use a dedicated test user and the correct auth type from day one — auth bugs surface late otherwise