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:
// CAP resolves the destination at runtime
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
# Bind the Destination Service locally
cds bind -2 my-app-destination
# Run in hybrid mode — CAP resolves destinations from BTP
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
BasicAuthenticationin production destinations -
✅ Use
OAuth2ClientCredentialsfor system-to-system,OAuth2JWTBearerfor user propagation -
❌ Forgetting the
connectivityservice binding for on-premise destinations -
✅ On-premise always needs both
destinationandconnectivityservices inmta.yaml -
❌ Hardcoding destination credentials in
package.json -
✅ Use
[development]profile for local mocks,[production]for real destinations -
❌ Using
OAuth2UserTokenExchangewhenOAuth2JWTBeareris available -
✅
OAuth2JWTBeareris preferred — it achieves the same result in one step -
❌ Testing principal propagation with
BasicAuthenticationduring development -
✅ Use a dedicated test user and the correct auth type from day one — auth bugs surface late otherwise