0

Getting Error Connecting to Subscriber Sub account destination connected to on-prem. system in cloud foundry from multitenant application from provider account via connectivity service and S4 SDK api . Same arrangement is working fine with the destination connection pointing to another on-premise system connected with provider subaccount .

Referring the SAP help which shows that connectivity service has this inbuilt capabality out of the box: https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/9c0bdd0efc8640739c9d2fa5cfe56cbd.html

getting following error when accessing Subscriber subaccount destination from Provider SAAS Application running in Provider Subaccount via S4 SDK API:

Complete Stack Trace :

"2019-04-09T11:25:03.714+0000 [APP/PROC/WEB/0] OUT { "written_at":"2019-04-09T11:25:03.708Z","written_ts":2225588987993569,"component_type":"application","component_id":"212c1a7d-c897-4834-8f7c-6e2a3d6bfed3","space_name":"Sandbox","component_name":"connectivity","component_instance":"0","organization_id":"-","correlation_id":"-","organization_name":"-","space_id":"f057513a-85e3-4229-b42f-f0fe7a058fa6","container_id":"10.0.75.11","type":"log","logger":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]","thread":"http-nio-8080-exec-6","level":"ERROR","categories":[],"msg":"Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destinations of subscriber service instance: Failed to get access token for destination service. If your application is running on Cloud Foundry, make sure to have a binding to both the destination service and the authorization and trust management (xsuaa) service, AND that you either properly secured your application or have set the "ALLOW_MOCKED_AUTH_HEADER" environment variable to true. Please note that authentication types with user propagation, for example, principal propagation or the OAuth2 SAML Bearer flow, require that you secure your application and will not work when using the "ALLOW_MOCKED_AUTH_HEADER" environment variable. If your application is not running on Cloud Foundry, for example, when deploying to a local container, consider declaring the "destinations" environment variable to configure destinations.] with root cause","stacktrace":["com.sap.cloud.sdk.cloudplatform.security.exception.TokenRequestDeniedException: Unable to get access token: XSUAA service denied request with HTTP status 401 (Unauthorized). Please make sure to correctly bind your application to a XSUAA service instance. Note that this error may also occur if you are using a service plan that is not suitable for your scenario. If you are building a SaaS application on Cloud Foundry, select service plan "application" when creating your XSUAA instance. If you are building a reuse service that should be consumed by other applications, select service plan "broker".","tat com.sap.cloud.sdk.cloudplatform.connectivity.TokenRequest.executeTokenRequest(TokenRequest.java:128)","tat com.sap.cloud.sdk.cloudplatform.connectivity.TokenRequest.requestTokenWithClientCredentialsGrant(TokenRequest.java:385)","tat com.sap.cloud.sdk.cloudplatform.connectivity.XsuaaService.requestAccessToken(XsuaaService.java:156)","tat com.sap.cloud.sdk.cloudplatform.connectivity.XsuaaService.getServiceToken(XsuaaService.java:216)","tat com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.getAccessToken(DestinationServiceCommand.java:111)","tat com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.run(DestinationServiceCommand.java:124)","tat com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.run(DestinationServiceCommand.java:28)","tat com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)","tat com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)","tat rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)","tat rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)","tat rx.Observable.unsafeSubscribe(Observable.java:10327)","tat rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)","tat rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)","tat rx.Observable.unsafeSubscribe(Observable.java:10327)","tat rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)","tat rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)","tat rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)","tat rx.Observable.unsafeSubscribe(Observable.java:10327)","tat rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)","tat com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)","tat com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)","tat com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)","tat rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)","tat java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)","tat java.util.concurrent.FutureTask.run(FutureTask.java:266)","tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)","tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)","tat java.lang.Thread.run(Thread.java:836)"] } 2019-04-09T11:25:03.754+0000 [RTR/5] OUT connectivity-test.cfapps.eu10.hana.ondemand.com - [2019-04-09T11:25:01.668+0000] "GET /odata/UserDetails HTTP/1.1" 500 0 1257 "https://.authentication.eu10.hana.ondemand.com/login" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-" "10.0.75.11:61046" x_forwarded_for:"-" x_forwarded_proto:"https" vcap_request_id:"eab68130-bfff-4cf2-733c-da051adfb1db" response_time:2.085981657 app_id:"212c1a7d-c897-4834-8f7c-6e2a3d6bfed3" app_index:"0" x_correlationid:"8e2d22b0-b4c7-4d20-5461-600aea37b2d2" x_b3_traceid:"7c4752638ec93577" x_b3_spanid:"7c4752638ec93577" x_b3_parentspanid:"-" b3:"7c4752638ec93577-7c4752638ec93577"

Please help.

Thanks, Siddharth

    if (TenantAccessor.getCurrentTenant().getTenantId().equals("<Subscriber tenet id>"))
            {
                final ErpConfigContext configContext = new ErpConfigContext("TEST_dest");

    else

    {
     < call provider destination using the above code with the destination belonging to Provider account >
    }
Rann Lifshitz
  • 4,040
  • 4
  • 22
  • 42
SCD
  • 89
  • 2
  • 10
  • 1
    You definitely need a binding to a service of each the XSUAA service and the destination service and configured security for your app. I cannot derive clearly from your question whether this is present. Have you ensured that all this is configured? Also, how did you create the subscription between the subscriber tenant and the app in the provider tenant? – Emdee Apr 18 '19 at 10:38
  • thanks for reply ,binding and everything is in place on provider account in CF ,after creating the subscription for the subscribe tenant using saas registry it is not working for subscriber tenant for destination service access: please check below link :https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/9c0bdd0efc8640739c9d2fa5cfe56cbd.html i am facing issue with approach Subscriber-Specific Destination mentioned in above link on SCP CF using SDK api hope this clarifies – SCD Apr 19 '19 at 07:03
  • 1
    Pls add the complete stacktrace of the DestinationAccessException. – Emdee Apr 23 '19 at 08:22
  • done please check – SCD Apr 23 '19 at 11:57
  • Which version of the S/4HANA Cloud SDK do you use? Which service plan do you use for your XSUAA instance? – Emdee Apr 24 '19 at 09:50
  • Hi Emdee ,i am using XSUAA Application service plan for my XS-APP,and SDK version is 2.13.3 . – SCD Apr 24 '19 at 14:30
  • Can you point out the purpose of the code above? Why would you use a different destination depending on the tenant ID? – Emdee Apr 26 '19 at 12:20
  • Hi Emdee, earlier i used the same name as of provider sub-account destination but it was not working so tried giving different destination name at subscriber sub account diffrent from provider subaaccount,both the approaches give same error. – SCD Apr 26 '19 at 13:52
  • idea is to get the data from subscriber sub-account destination which is connected with different on prem. system specific to Subscriber ,when tenant specific APP url is called post subscription as per the approach Subscriber-Specific Destination mentioned in the url: https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/9c0bdd0efc8640739c9d2fa5cfe56cbd.html – SCD Apr 26 '19 at 13:57

2 Answers2

4

Have you implemented the subscriber callback services in your application as described here? https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/ff540477f5404e3da2a8ce23dcee602a.html

The more important one is the getDependencies callback (Procedure step 2). I know it says optional, but when using services like destination it is necessary. It's needed so that during subscription, the SaaS Provisioning service knows to configure the destination service to authorize the subscriber account.

Also, if this was not implemented before: After implementing and re-deploying the application, the subscription process needs to be re-done for the necessary configuration to take effect.

  • Thanks Pablo ,will check your suggestions and get back if works. – SCD Apr 30 '19 at 07:26
  • 1
    Hello Pablo,how i can get xs app name and id of XSUAA service while implementing the dependency call back ,all i can find is the xsapp name of my application and id in service keys and environment variable ,please clarify. – SCD May 10 '19 at 08:26
  • 1
    These can be found in the VCAP_SERVICES environment variable. In VCAP_SERVICES, each bound service has an object, e.g. "connectivity": [...], "destination": [...] and so on. Within each of these objects you can find the value you need for "xsappname" under credentials.xsappname. I would try the suggested way with the one "xsappname" property instead of the two "appName" (same value as "xsappname") and "appId" (name of service type you see in VCAP_SERVICES, e.g. "destination"). – Pablo Caceres May 13 '19 at 14:05
  • 1
    You also don't need to return an entry for the XSUAA service, just the other important services such as connectivity and destination. – Pablo Caceres May 13 '19 at 14:05
2

To achieve this, you need to return the xsappname of your destination service as dependency in getDependecies callback(like below)

@GetMapping(value = "/callback/v1.0/dependencies")
        public List<DependantServiceDto> callbackGet() {
            String logMessage = "callback service successfully called with RequestMethod = GET for tenant ";
            //logger.info(logMessage);
            List<DependantServiceDto> dependenciesList = new ArrayList<>();
            JSONObject vcap;
            String destinationXsAppName = "";
            try {
                vcap = new JSONObject(System.getenv("VCAP_SERVICES"));
                JSONArray arr = vcap.getJSONArray("destination");
                JSONObject credentials = arr.getJSONObject(0).getJSONObject("credentials");
                destinationXsAppName = credentials.getString("xsappname");
                if(!destinationXsAppName.isEmpty()){
                    dependenciesList.add(new DependantServiceDto(destinationXsAppName));
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return dependenciesList;
        }

Remember to do the subscription again if you have already done.

Once you are done, you can generate the Bearer taken using subscriber subdomain and credentials(client id and secret) from the destination service.

https://subacriber-subdomain.authentication.sap.hana.ondemand.com/oauth/token?grant_type=client_credentials&response_type=token

Pass the Bearer token to destination service API to read the subscriber account destinations.

https://destination-configuration.cfapps.sap.hana.ondemand.com/destination-configuration/v1/destinations/destinationName