Skip to Content
Technical Articles
Author's profile photo Matthieu Pelatan

Part 2: How to use SAP Cloud Platform Connectivity and Cloud Connector in the Cloud Foundry environment

*********** Updates ************

Last update on 09.08.2017

See details at the end of the blog

**********************************

 

In the first part of the blog, I’ve described how to establish a secure tunnel between the SAP Cloud Platform Trial (Cloud Foundry environment) and the Cloud Connector. In addition to that we have configured an Access Control so that we can now access and consume securely data from an on-premise system.

In the second part I will explain how to configure SAP Cloud Platform Connectivity so that a web application can consume the odata service of the existing on-premise system.

Note: many configuration steps of this blog will be done via the SAP Cloud Platform cockpit. Be aware that you can do exactly the same thing via the Command Line Interface of Cloud Foundry. More details about the CLI can be found here.

 

First let’s take a moment to see how it works for basic authentication:

SAP-CP-Connectivity-CF.png

1. User calls the webApp through the AppRouter, which provides a central point of entry to business applications.

2. The request is redirected to XSUAA and the user needs to login. Then a JWT1 (JSON Web Token) is created and sent to AppRouter. JWT1 is then cached by the AppRouter.

3. AppRouter forwards the request to the relevant Web-app URL which is defined as destination, it also passes the JWT1 token with credentials.

4a. The WebApp requests a JWT2 to access the destination instance. JWT2 should be cached for better performance.

4b. In parallel the WebApp requests a JWT3 to access the connectivity instance. JWT3 should be cached for better performance.

5. The WebApp requests destination configuration by sending JWT2.

6. The WebApp sends request to the connectivity instance with JWT3 and the Authorization header.

7. SAP Cloud Platform Connectivity forwards request to the Cloud Connector.

8. Cloud Connector sends request to the on-premise system.

Now that you know how it works, let see what are the steps needed to configure such a scenario:

  1. Creation of the destination and the destination instance
  2. Creation of the connectivity instance
  3. Creation of the XSUAA instance
  4. Configuration and deployment of the AppRouter
  5. Configuration and deployment of the WebApp

Then let’s do it together and start with the destination…

 

1. Creation of the destination and the destination instance

The destination service, which is available (beta) since October 2017, allows you to store securely settings such as your credentials, the protocol, the URL of the on-premise system, and the proxy type. Destinations are defined on the Subaccount level and you can integrate them in your application on the space level. You can find more details in the official documentation: https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/7e306250e08340f89d6c103e28840f30.html

 

To create a destination, go the SAP Cloud Platform cockpit and navigate to your Subaccount. Then go to “Destinations (beta)” under “Connectivity” and create a new destination.

Configure now your destination so that you can consume the data from the virtual host previously defined in the Cloud Connector.

Note: if you are using the app available in the sharepoint, be sure to use the same name of the destination or change it in the webApp directly.

 

Now that we have the destination defined, we can create a destination instance in the space. Go to the section “Services Marketplace” under the “Services” tab and click on the Destination tile.

Then click on the “Instances” section and create a new instance.

Keep “lite” as plan and click “Next”. Then skip the next 2 wizard options (Parameters, Application assignment) and add an instance name (e.g. “destination-demo-lite”). There are different ways to bind the application to the destination service. We will do it later on by adding the name of the destination instance in the manifest of the application. During the deployment of the app, the binding will be then added automatically.

 

2. Creation of the connectivity instance

SAP Cloud Platform Connectivity provides a standard HTTP proxy for on-premise connectivity to be accessible by any application. Proxy host and port are available in the credentials of the bound connectivity service via the environment variable “VCAP_SERVICES”. More details on how to interpret VCAP_SERVICES can  found in the official CF documentation.

In order to consume the data coming from the on-premise in the application via the HTTP proxy, we need to create an SAP Cloud Platform Connectivity instance and bind it to the application. When a binding is created the application gets connectivity credentials in its environment variables. More details about it here.

Ok, let’s create an connectivity instance as we did for the destination instance! Go to the “Services Marketplace” under the “Services” tab and click on the Connectivity tile.

Then click on the “Instances” section and create a new instance.

Keep “lite” as plan and click “Next”. Then skip the next 2 wizard options (Parameters, Application assignment) and add an instance name (e.g. “connectivity-demo-lite”). Like the others instances, the binding will be done by adding the instance in the manifest of the application later on.

 

 

3. Creation of the Authorization & Trust Management instance (aka. XSUAA)

This central identity management service for the Cloud Foundry environment manages application authorizations and the trust to identity providers.

By calling the application, the user will be redirected to the XSUAA and will be prompt to give his credentials. It will then achieve certain checks like verifying the OAuth client, client’s scopes, user’s scopes (Scopes are permissions to access one or more resources). Assuming everything is fine, the user will be authenticated and the XSUAA will redirect the browser to the application.

In a second step the application will take the client Id and the client secret and will talk directly with the XSUAA to get an access token. Then the application will sent both tokens as HTTP header so that it can consume the backend system via the SAP Cloud Platform Connectivity.

The next step is then to create an instance for the XSUAA. We open the SAP Cloud Platform cockpit and go to the “Services Marketplace” under the “Services” tab and click on the XSUAA tile.

Then click on the “Instances” section and create a new instance.

In the wizard we keep “application” as service plan and click “Next”. Then we add the following parameters in the editor and then click on “Next”.

{
        "xsappname" : "connectivity-app-demo",
        "tenant-mode": "dedicated"
}

In the last step of the wizard, we can add an instance name (e.g. “xsuaa-demo”). The same name will be added in the manifest of the application later on.

Note: As mentioned before, we will bind the instance at the end, once we have deployed the application.

4. Configuration and deployment of the application router

For this demo I have preconfigured a standard application router. Is it really needed? No but it makes my life easier and it’s a kind of best practise in the Cloud Foundry world. So in our scenario the application router is the component that acts as our oAuth Client. Concretely that means that by calling the application router in the browser, the end-user will be redirected to the XSUAA in order to login.

Note: probably you want to try it by yourself and you need maybe a standard application router. No problem, SAP provides an NPM registry under the following URL: https://npm.sap.com/

Use the following command to configure the NPM registry for your user

npm config set @sap:registry https://npm.sap.com/

Use the install command to download the approuter and its dependencies

npm install @sap/approuter

Now let configure the manifest file of the application router before we deploy it.

  1. Name of the application router
  2. Hostname of the application router:
    1. Be aware that it should be unique, then you can for example add you trial-user to the name. In my case it would be “approuter-demo-p193274639trial”).
    2. Do not use any underscore in the hostname. It may contain only the ASCII letters ‘a’ through ‘z’, the digits ‘0’ through ‘9’, and the minus sign.
  3. URL of the web application (based on the app name that will be defined in the application’s manifest). Don’t forget to update the url with your hostname (appname+trial-user-name)
  4. Name of the XSUAA instance (the name has been previously defined in the SAP Cloud Platform cockpit by creating the XSUAA instance)

Here is the code of our application router manifest:

---
applications:

- name: approuter-demo
  host: approuter-demo-p193274639trial
  buildpack: nodejs_buildpack
  memory: 128M
  path: ./
  env:
    NODE_TLS_REJECT_UNAUTHORIZED: 0
    destinations: >
      [

           {"name":"dest-to-app", "url" :"https://connectivity-app-demo-p193274639trial.cfapps.eu10.hana.ondemand.com", "forwardAuthToken": true },
           {"name":"ui5", "url":"https://sapui5.hana.ondemand.com/1.42.6/resources/"}
      ]
  services:
    - xsuaa-demo

In order to deploy the application router, we go to the “Applications” section in the SAP Cloud Platform cockpit. There we can click on “Deploy Application” and add the archive file and the manifest.

As we have defined the XSUAA service in the manifest, the binding will be done automatically. You can verifying it by clicking on the application router name and then on the “Service Bindings” section.

 

5. Configuration and deployment of the web application

The web application consists of 2 groups:

  1. JAVA logic to handle the JWT token and create a request via the HTTP Proxy of the SAP Cloud Platform Connectivity
  2. UI5 Frontend to display the result of the request in a table (Products and prices)

 

The manifest file of the application should also be configured:

  1. Name of the application
  2. Hostname of the application:
    1. Again here the hostname should be unique. So add you trial-user to the name. In my case it would be “connectivity-app-demo-p193274639trial”
    2. Do not use any underscore in the hostname. It may contain only the ASCII letters ‘a’ through ‘z’, the digits ‘0’ through ‘9’, and the minus sign.
  3. Name of the XSUAA instance defined previously
  4. Name of the Connectivity instance defined previously
  5. Name of the Destination instance defined previously

Here is the code of the manifest:

---
applications:

- name: connectivity-app-demo
  host: connectivity-app-demo-p193274639trial
  buildpack: java_buildpack
  memory: 512M
  instances: 1
  path: target/connectivity.war
  env:
        # Accept any OAuth client of any identity zone 
        SAP_JWT_TRUST_ACL: '[{"clientid":"*","identityzone":"*"}]'
       # Useful on a dev environment
       SKIP_SSL_VALIDATION: false
       xsuaa_connectivity_instance_name: "xsuaa-demo"
       xsuaa_destination_instance_name: "xsuaa-demo"
      JAVA_OPTS: '-Xss349k'
      services:
      - xsuaa-demo
      - connectivity-lite
      - destination-lite

Note: by changing the name of the application, a change needs to be done in the file application.properties. You can find it here: /src/main/webapp/security/xs-security.json.

# parameters of the app
xs.appname=connectivity-app-demo

Before deploying the web application, let take time to see where the magic happens. The most important file is the connectivity servlet, which is responsible to propagate the user JWT token via headers.

// get value of  "onpremise_proxy_host" and "onpremise_proxy_port"
 ...

// set up the on-premise HTTP Proxy
URL url = new URL("http://virtualhost:1234");
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(connProxyHost, connProxyPort));
urlConnection = (HttpURLConnection) url.openConnection(proxy);
 
// insert the necessary headers in the request
urlConnection.setRequestProperty("SAP-Connectivity-Authentication", "Bearer " + jwtToken1);
urlConnection.setRequestProperty("Proxy-Authorization", "Bearer " + jwtToken2);

// Optionally, if configured, add the SCC location ID
urlConnection.setRequestProperty("SAP-Connectivity-SCC-Location_ID", "New York");

For more details, you can can download the full code at the bottom of the page.

In order to deploy the web application, we go again to the “Applications” section in the SAP Cloud Platform cockpit. And again we click on “Deploy Application” and add the archive file and the manifest.

To verify that the manifest has taken care of the binding, we can check the “Service Bindings” section of the web application if the services have been added.

That’s all! Now we can call the application in the browser. In order to get the URL, we go to the “applications” tab and click on the “approuter-demo”. Here we can find the URL of the application router.

The route to the web application has been configured in the /approuter/xs-app.json file of the application router,  so that we need to add “/app/” at the end of the URL.

{
        "welcomeFile": "index.html",
        "routes": [{
                "source": "/app",
                "target": "/",
                "destination": "dest-to-app"
                  }
        ]
}

Click on the link “Go to App” to called the URL: https://approuter-demo.cfapps.eu10.hana.ondemand.com/app/ 

Note: by calling this URL, the destination “dest-to-app” defined in the manifest of the appRouter” will be called. Here again a copy of the manifest.

---
...
    destinations: >
      [

           {"name":"dest-to-app", "url" :"https://connectivity-app-demo-p193274639trial.cfapps.eu10.hana.ondemand.com", "forwardAuthToken": true },
           {"name":"ui5", "url":"https://sapui5.hana.ondemand.com/1.42.6/resources/"}
      ]
 ...

 

By opening this URL in the browser, the user will be redirected to the XSUAA in order to login.

After the login, the XSUAA redirects the user to the web application, which called the odata services of the on-premise system via the Cloud Connector. Here is then the result.

You want to try it by your own or you want to see the code in details. No problem, you can download the code here. Some improvements need to be done for sure (for example the way to save the backend credentials 😉 So at least I hope it helps you to better understand how to use the the SAP Cloud Platform Connectivity in the Cloud Foundry environment.

In the next part of this blog serie, I will explain how to replace basic authentication with principal propagation.

Stay tuned and send me your feedback.

Matthieu

 

Here again the repository with the code.

 

For principal propagation related questions, please have a look at the 3rd part of the blog series.

 

*********** Updates ************

10.11.2017: Due to new buildpack, the manifest file of the web application has been updated.

27.11.2017: Extract the SAPUI5 Library of the webApp + Adding a destination for SAPUI5 in the manifest of AppRouter.

15.12.2017: Adding the steps for using the SAP Cloud Platform Destination Service.

09.01.2017: Small improvements in the blog for a better understanding, for example adding the p-user to the hostname in the manifest.

01.03.2018: Hint that you should not use any underscore in the hostname of the appRouter or the application.

09.08.2018: Added the link of the 3rd part of the blog series explaining how to use principal propagation.

**********************************

 

Assigned Tags

      93 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Murali Shanmugham
      Murali Shanmugham

      Hi Matthieu, Thanks for posting this. Been waiting for this. Will try it out and give you a feedback. Cheers

      Author's profile photo Former Member
      Former Member

      Question about "you can can download the full code at the bottom of the page". What link on this page could be used exactly?

      thanks and regards,

      Gennady

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Gennady,

      you can find the link at the bottom of the page:

      You want to try it by your own or you want to see the code in details. No problem, you can download the code here

      Let me know if you have problem with the link.

      Best,

      Matthieu

      Author's profile photo Bert Deterd
      Bert Deterd

      The link does not work. Could you please restore the link?

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Thanks for the hint. I have updated the expiration date. It should be fine now.

      Author's profile photo Robert Eijpe
      Robert Eijpe

      The link does not work. Could you please restore the link?

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Robert, can you please try again? Thanks.

      Author's profile photo Jaglika Perkova
      Jaglika Perkova

      The link has expired. Would you mind resharing it please? Thank you in advance.

      Author's profile photo Thiago Oliveira
      Thiago Oliveira

      Hey Matthieu, could you update the link again please?

      Author's profile photo Serban Petrescu
      Serban Petrescu

      Hi Matthieu,

      I am not able to find any documentation on the Principal Propagation for CF. Based on the Cloud Connector itself, I guess it should be possible (I see that you added support for the JWT-based SSO by extracting the principal from the token).

      Could you indicate where we could find some documentation on this feature? Also, is this feature "official" or still "beta" (i.e. work-in-progress)?

      Thanks,
      Serban

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Serban,

      indeed Principal Propagation works already in the Cloud Foundry environment. We working on the 3rd part of the blog, which will describe it in details. Stay tuned...

      Matthieu

      Author's profile photo Serban Petrescu
      Serban Petrescu

      Hi Matthieu,

       

      Thanks a lot for the fast response! Can't wait for your next blog 😉

       

      Serban

      Author's profile photo Petr Shumilov
      Petr Shumilov

      Hi Matthieu,

      I am developing node.js application in the Cloud Foundry environment and I need to able connectivity with on-promise OData service (through SAP Gateway). I followed your instructions but when I started implement proxy connection one thing made me confused. I did not understand how determine jwtToken1. Where and how i can get it? I read your java code and this doc but still did not understand. I hope you can help me))

      Thank you in advance,
      intern Petr

      Author's profile photo Former Member
      Former Member

       

      Petr, as far as I can see, a jwt determination example code is in the code provided my Matthieu “at the bottom of the page” (at the end of his blog) in the ConnectivityServlet.java file,

      getClientOAuthToken() function

       

      Author's profile photo Simen Huuse
      Simen Huuse

      Hi Matthieu! Great blog!

      Do you have any info on when the connectivity services will become available for the US West (CA) Beta site?

       

      All the best,

      @simenhuuse

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Simen,

      we are working on making it asap available on US West (CA) but unfortunately I can't give a date right now. Stay tuned!

      Best,

      Matthieu

      Author's profile photo Yangyang Chen
      Yangyang Chen

      Hi Matthieu,

       

      Thank you for this wonderful blog!

       

      We are wondering whether we can directly consume Connectivity service from UI level? If not, can we implement similar logic in NodeJS instead of Java code?

       

      Thanks in advance

       

      yangyang

      Author's profile photo Former Member
      Former Member

      Did you find out anything in regards to implementing similar logic in nodejs?

      Regards,

      Sindre

      Author's profile photo Former Member
      Former Member

      Hello,

      cannot opt enough for a node js oriented version of a simple connectivity/destination(?) scenario!

      Thanks,

      Adam

       

      Author's profile photo Bert Deterd
      Bert Deterd

      Made a small npm package scc-connector which might be of help if you want to build a plain Node.js app for cloud foundry sap cloud platform with xsuaa and connectivity.

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Sounds good. I will have a look at it 😉 Thanks.

      Author's profile photo Former Member
      Former Member

      Hi! Great work, that is exactly what I want to achieve. However, I am facing some difficulties, so I think I am doing something wrong.

       

      what I have done is the following:

      defined env variable in manifest.yml:

      env:
      SAP_SCC_VIRTUAL_HOSTS: '["xxx:xxx"]'
      in server.js:
      var express = require( 'express')
      var app = express()
      var sccConnector = require('scc-connector');
      app.use(sccConnector);
      What happens when i do a request to root (/) now is just a 'Error' in the console. What am I doing wrong? 🙂 Thanks.
      Author's profile photo Tobias Trapp
      Tobias Trapp

      Hi Matthieu,

      great and very helpful blog!

      One question concerning your code example:

      There's a dependency to group "com.sap.xs2.security", artifact "java-container-security", which doesn't seem to be public available. Are there any plans to move this into Maven Central or are there any alternatives?

      I'm doing something similar to your example but making use of Spring instead of the Servlet API and there I'm having trouble with the Spring Security configuration. I guess, that this is provided by the formerly mentioned artifact...

      Thanks,

      Tobi

      Author's profile photo Philipp Stehle
      Philipp Stehle

      Hey Tobi,

       

      sorry for the delay.

      You can get the artifact here https://launchpad.support.sap.com/#/softwarecenter/search/XS_JAVA

      Installation instructions are available here: https://help.sap.com/viewer/4505d0bdaf4948449b7f7379d24d0f0d/2.0.02/en-US/8783c06f6d5a48e791e7ad17d49a95c0.html

      You'll have to change the version of the dependency declaration to the one provided in the zip file to make it compile.

      I didn't know that it's not available in Maven Central. Possibly because of legal reasons, but I don't know why. Sorry about that.

       

      Thanks for reporting,

      Philipp

      Author's profile photo Sarthak Sharma
      Sarthak Sharma

      Hi Matthieu,

       

      An execellent tutorial. It did help me in past. However, currently I'm working on a UI5 application on CF which needs to connect to another CF application through destinations. I understand the process to use destinations in CF is different than in Neo. There're references for making a request through destination using JAVA, however, I couldn't find any resources on how to do so in UI5 application. Can you please assist me with this? Or, do I've to create an MTA project, make the request through JAVA code and display the data in UI5 application? Any help will be much appireciated.

      Kind Regards,

      Sarthak

      Author's profile photo Philipp Stehle
      Philipp Stehle

      Yes, you'll need an application acting as a proxy here.
      It's not necessary to write this application using Java, but it has to run in the cloud (not in the users browser).

      There are two (maybe more) solutions:

      1. A very simple application, which allows your UI5 application to fetch the connectivity details and the UI5 applications connects directly to your second CF application.
      2. A (quite more complex) application which fetches the connectivity details and executes the request on behalf of the UI5 application and redirects the result.

      While the first solution should be easier to implement and provide better performance, it is not usable if the CF application requires authentication using some kind of technical user (as those credentials would be exposed to the users browser).

      Author's profile photo Former Member
      Former Member

      Hi Philipp,

      As described in sample code, only 'HTTP' protocol supported here.

      // set up the on-premise HTTP Proxy

      URL url = new URL("http://virtualhost:1234");

       

      My question is, can we use 'https' protocol as virtual host principle?

      URL url = new URL("https://virtualhost:1234");

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Liam,

      the protocol used between the Connectivity service and the Cloud Connector is HTTP. HTTPS is not needed as the connection is protected via the secure TLS tunnel.

      Best,

      Matt

      Author's profile photo Sarthak Sharma
      Sarthak Sharma

      Thanks a lot Philipp Stehle and Former Member for your suggestions. Yes, these are probable solutions, however, I found an easier and safer solution to this. Just add a destination in the env variable in the application manifest file which works similar to adding destinations in Neo environment. Moreover, you can use this destination in UI5 application the same way as in Neo environment. Here's a sample code for reference:

      - name: cf-ui-app
      buildpack:nodejs_buildpack
      memory:128M
      instances:1
      env:
      destinations:>
      [
      {
      "name":"dest",
      "url":"https://<app-url>.cfapps.eu10.hana.ondemand.com/",
      "forwardAuthToken":true
      }
      ]
      Author's profile photo Ram Prasath Satheesh
      Ram Prasath Satheesh

      Is it possible to use Basic Authentication in the above.

      Author's profile photo Sarthak Sharma
      Sarthak Sharma

      Yes, you can. But for this, you've to use SAP's provided JAVA based connectivity app which access CF destinations and forward your request. And in the destination, you use basic authentication.

      Author's profile photo Jan Mattfeld
      Jan Mattfeld

      Sarthak Sharma Can you eloborate a bit more?

      I sucessfully connected a UI5 app, using the MTA CF deployment feature of Web IDE Full-Stack. It created the connectivity and uaa services automatically.

      However, the app prompts for basic auth at startup. On entering valid backend credentials, it works just fine.

      I already selected basic authentication in the CF destination settings and stored the same user/password combination. Yet, the auth popup in the deployed UI5 app still appears.

      Any hint would be appreciated.

      Regards,
      Jan

      PS @Ram Prasath Satheesh did you have any luck?

      Author's profile photo Sarthak Sharma
      Sarthak Sharma

      Hi Jan,

      The credentials you stored in the destination is for the destination only. This means, whenever you use the connectivity and destination services to connect to another system, those credentials will be used. However, the one that you're prompted to enter while opening your app are for the XSUAA service. Whenever you run the app for the first time, it'll authenticate you. If you don't want this and want to make your app public, you can unbind the XSUAA service reference from your app. Moreover, whenever your app uses the destination, it uses the credentials stored with the destination.

      I can describe more once I look at your xs-app.json file.

      Hope this helps.

      Regards,

      Sarthak

      Author's profile photo Jan Mattfeld
      Jan Mattfeld

      Thanks for your quick reply!

      I did know about the UAA service, so the first login with CF credentials is expected.

      However, the app does not use the stored authentication for the destination. So after CF login, there is an additional basic auth browser popup, asking for the backend credentials. That's what puzzles me.

      Author's profile photo Ram Prasath Satheesh
      Ram Prasath Satheesh

      Hi Jan,

      Yes, I'm able to connect and it is working for us.

       

      Usually, the scenario which you mentioned won't happen. If it is happening, it could be because of the below scenarios

      • you are trying to connect to a system in a non-default client. ( It can easily be resolved by using ?sap-client=clientId in metadata call).
      Author's profile photo Jonathan Gross
      Jonathan Gross

      Sarthak Sharma Do you mean that you do not use xsuaa and the app router? I do not understand what you are explaining here. How do you get the credentials to access the destination?

      I am developing a reactjs frontend, and I would like to access the destination. But the app router does not want to direct to my app after login as my app is browser based and not a server.

      Thank you!

      Author's profile photo Sarthak Sharma
      Sarthak Sharma

      Hi Jonathan Gross,

      What I described above is a way to create a destination through env variable that will be specific to an app only. You can either create a destination for your app this way, otherwise, you can try to access the SCP Destination service APIs using the binding-variables. This following blog should be helpful:

      https://blogs.sap.com/2018/10/08/using-the-destination-service-in-the-cloud-foundry-environment/

      Hope this helps.

       

      Author's profile photo Parul Agrawal
      Parul Agrawal

       

      Hi Matthieu,

      I am done with the part 1 of this blog https://blogs.sap.com/2017/07/09/how-to-use-the-sap-cloud-platform-connectivity-and-the-cloud-connector-in-the-cloud-foundry-environment-part-1/

      In the part 2 of this blog, I am done with the step 1 : ‘Creation of the destination and the destination instance’.

      But when I following the step 2 for ‘Creation of the connectivity instance’ , I am not able to create the destination service either via SCP cloud foundry trial account or through the command prompt as well( CLI ).

      I am getting the below mentioned error :

      “Unable to create service instance. We are sorry, but we have encountered an internal error. If the problem persists, please create a support ticket.

      Service broker error: Org with guid [e3eb2f49-05ea-40a6-be7e-5f5e1b55ac57] is not registered in tenant-onboarding service. Instance creation not allowed.”

      Below is the screenshot for reference :

       

       

      Is there anything which I missed or something needs to maintained in cloud foundry trial account with respect to registration, configuration ?

      Would you please provide some insights on this ?

      Thanks you.

      Best Regards, Parul

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

       

      Hi,

      please ask the admin of the global account to add quotas (destination service) for your subaccount in the entitlement section of the global account. Then you should be able to create an instance.

      Hope it helps.

      Matt

      Author's profile photo Parul Agrawal
      Parul Agrawal

      Author's profile photo Aileen Zhou
      Aileen Zhou

      I have the same issue. Is there a solution? Thank you!

      Author's profile photo Gustavo Kath
      Gustavo Kath

      I'm having with the same issue. Did someone find a solution for this?

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi,

      please ask the admin of the global account to add quotas (destination service) for your subaccount in the entitlement section of the global account. Then you should be able to create an instance.

      Hope it helps.

      Matt

      Author's profile photo Chao Zhang
      Chao Zhang

      Looking forward to the part 3 principal propagation!

      Author's profile photo Former Member
      Former Member

      Hi Matthieu,

      The Source code link given at the bottom of the page has expired. Can i request you to please restore the link ?

      Thanks,

      Ramesh

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Ramesh,

      thanks for the feedback. The link has been now updated.

      Best,

      Matthieu

      Author's profile photo Former Member
      Former Member

      Hi Matthieu,

       

      I tried to connect my UI application using the reference from the source code given at end of the page. Below are the destination and manifest i am using. The app router works fine as well as the UI application works fine but the application is not able to get Destination from the cockpit and further doesn't connect to the onPremise system. Is there anything missing?

       

      Manifest.yml file for connectivity app :

       

      ---
      applications:

      - name: connectivity-app-demo
      host: connectivity-app-demo-Masterdata
      buildpack: java_buildpack
      memory: 512M
      instances: 1
      path: target/connectivity-sample.war
      env:
      # Accept any OAuth client of any identity zone
      SAP_JWT_TRUST_ACL: '[{"clientid":"*","identityzone":"*"}]'
      # Useful on a dev environment
      SKIP_SSL_VALIDATION: false
      xsuaa_connectivity_instance_name: "xsuaa-demo"
      xsuaa_destination_instance_name: "xsuaa-demo"
      JAVA_OPTS: '-Xss349k'
      services:
      - xsuaa-demo
      - connectivity-demo-lite
      - destination-demo-lite

       

      neo-app.json route definition:

       

      {
      "path": "/MASTERPROJECT",
      "target": {
      "type": "destination",
      "name": "abapBackend1",
      "entryPath": "/sap/opu/odata/sap/CPD_MASTERPROJECT_OVERVIEW_SRV/"
      },
      "description": "MASTERPROJECT"
      },

      approuter-manifest.yml file :

       

      ---
      applications:

      - name: connectvity-demo-approuter
      host: connectvity-demo-approuter
      buildpack: nodejs_buildpack
      memory: 128M
      path: ./
      env:
      NODE_TLS_REJECT_UNAUTHORIZED: 0
      destinations: >
      [
      {"name":"dest-to-app", "url" :"https://connectivity-app-demo-masterdata.cfapps.eu10.hana.ondemand.com", "forwardAuthToken": true },
      {"name":"ui5", "url":"https://sapui5.hana.ondemand.com/1.46.6/resources/"}
      ]
      services:
      - xsuaa-demo

       

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Kumar,

      have you called your destination "abapBackend1" or are you using maybe another name? Can you please check in the SCC if it receives at least the request?

      Best,

      Matt

      Author's profile photo Guilherme Dellagustin
      Guilherme Dellagustin

      Hi Matthieu,

      Even though it may be obvious that JWT in this context means a JSON Web Token, I would suggest that in your first mention you change it to:

      "Then a JWT1 (JSON Web Token) is created and sent to AppRouter. JWT1 is then cached by the AppRouter."

      Linking it to https://jwt.io/

      Good job keeping this blog, it is very helpful and easy to follow.

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Thanks for the feedback, I have added your comment in the blog 😉

      Author's profile photo Venu Ravipati
      Venu Ravipati

      Hi Matthieu,

      Thanks for the great blog.

      I downloaded applications from the given link and could deploy the App router application just fine in Cloud foundry.

      But could not deploy the  demo application. Please find the screenshots below

      Getting below Error in Log:

      I tried with deploying both zip as well as war file. Neither could not be deployed successfully.

      Could you please help with any suggestions.

      Thank you and Best Regards,

      Venu

      Author's profile photo Venu Ravipati
      Venu Ravipati

      Deployment worked when deployed using cf push.

      Thank you,

      Venu

       

      Author's profile photo Gokulraj Ramdass
      Gokulraj Ramdass

      HI Matthieu., Nice Blog.. Waiting for BLOG 3.. using principal propagation in CF. When can we expect ur blog 3.. eagerly waiting.. 🙂

       

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      You can now find it here...

      Author's profile photo Arun Suresh
      Arun Suresh

      Hi ,

      We have a multi-tenant solution which exposes REST APIs to be consumed by tenants. We have created a service broker implementation for our app. A customer would create a subaccount and then create a service instance of our service and generate a service key. Using this service key, they can access our APIs.   The customer may also be using a S4 cloud/OnPremise backend system.

      Now, if we have to implement a feature which requires a connection to the customer’s backend system, how do we use the destination and connectivity services in such a multi-tenant scenario?

      Regards,

      Arun

      Author's profile photo Wolfgang Röckelein
      Wolfgang Röckelein

      Hi Arun,

      did you already found some documentation to combine multitenancy with onpremise access on CF?

      Thanks,

      Wolfgang

      Author's profile photo Former Member
      Former Member

      Hi,

       

      Thanks for sharing this block it is really helpful.

      But while trying to upload the connectivity-app-demo (code.zip, connectivity-app-demo-manifest.yml) i am getting the following error in the log,

      ERROR Finalize failed with exception #<RuntimeError: No container can run this application. Please ensure that you've pushed a valid JVM artifact or artifacts using the -p command line argument or path manifest entry. Information about valid JVM artifacts can be found at https://github.com/cloudfoundry/java-buildpack#additional-documentation. >
      2018-03-21T06:32:33.645+0000 [STG/0] ERR No container can run this application. Please ensure that you've pushed a valid JVM artifact or artifacts using the -p command line argument or path manifest entry. Information about valid JVM artifacts can be found at https://github.com/cloudfoundry/java-buildpack#additional-documentation.
      2018-03-21T06:32:33.650+0000 [STG/0] ERR Failed to compile droplet: Failed to run finalize script: exit status 1

      Kindly help how to resolve this, i tried using the cf push also its giving the same issue.

       

      Regards,

      Rumeshbabu S

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Rumeshbabu,

       

      based on your comment I assume that you have taken the wrong file. The zip name "code.zip" is more to have a look at the Java code or even if you want to change anything in the code. So the project need to built so that you can upload it to the SAP Cloud Platform 😉

      You will find on the sharepoint another file called "connectivity-app-demo.war". This should work with this file.

      Best,

      Matthieu

      Author's profile photo Former Member
      Former Member

      Hi,

       

      Thanks for the information, i tired with connectivity-app-demo.war with the manifest file and now i am getting following error.

       

      "Unable to upload application connectivity-app-demo. We are sorry, but we have encountered an internal error. If the problem persists, please create a support ticket.."

       

      Not sure what is going wrong, i am attaching my manifest.yml

      Thanks,

      Rumeshbabu S

      Author's profile photo Raúl Mayas
      Raúl Mayas

      Hi Matthieu,

       

      First of all, thanks for this blog.

      I’m having problems “approuter” app during the upload to cloud via terminal…

      The message that log generates it’s about parsing JSON when the cloud is trying to execute “approuter.js” file inside approuter package (@sap/approuter).

      I also tried the same version of approuter that you have used in your application and it failed again.

       

      Here is the error message:

       

      Did you have the same problem in any part of your development process?

      Is there anything that i can do to solve it?

       

      Regards,

      Raúl M

       

      Author's profile photo Matan Elitzur
      Matan Elitzur

      Hello Matthieu

      Very nice blog!!!

      My question is, you created a destination, connectivity and a trust service.

      But how you reference the destination you created in the cookpit "abapBackend1"?

      and how you can get the data from the abapBackend1 destination via the application that has the reference to the destination

      Thanks

      Matan

      Author's profile photo Philipp Stehle
      Philipp Stehle

      Hi Matan.

      I'm glad you liked the blog.

      Please take a look at the documentation of the Destination Service regarding Cloud Foundry Environment (https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/7e306250e08340f89d6c103e28840f30.html). It should contain any information you need. In case you still have problems let me know.

       

      Kind Regards,

      Philipp

      Author's profile photo Matan Elitzur
      Matan Elitzur

      Philipp, thanks for your answer.

      In my case I don't need to connect to Cloud Portal,

      I need to get odata from success factor landscape, so I configure a destination in the cookpit (like in the example "abapBackend1"),

      and I created an MTA application in CF that contain UI5 application. The UI5 application supposed to get data from success factor via odata.

      So I think I should config my ui5 application router and maybe also app-router

      So I created a destination service and bind it to the MTA application, but several pieces are missing from my side.

       

      Author's profile photo Former Member
      Former Member

      Hi.

      I would like to use the connectivity-app url in my custom MTAR application,

      i need to use this URL https://connectivity-app-demo-p193274639trial.cfapps.eu10.hana.ondemand.com to connect to my on-premise system from my custom MTAR application.

      I tried under required resources and modules at yaml file, but i am getting 404 not found error, Please help me how to use that URL as micro service in my custom MTAR application, here in my mtar application the app router will be defined by default.

      Thanks,

      Rumeshbabu S

      Author's profile photo Wolfgang Röckelein
      Wolfgang Röckelein

      Hi Matthieu,

      we can't you/SAP/we extend the application router to do this jwt "shuffling" needed for the onpremise access? Why would one need a separate web application just for this? Isn't this better done in the application router which does already some jwt handling?

      Regards,

      Wolfgang

      Author's profile photo Tobias Mitter
      Tobias Mitter

      Hi Wolfgang,

      I just replied with the same question as you had. Do you have any ideas until now?

      Thanks,

      Tobias

      Author's profile photo Wolfgang Röckelein
      Wolfgang Röckelein

      Hi Tobias,

      well, we could try to extend the application router ourselves. Unfortunatly I am currently lacking time to do this.

      Besides that I hope that somebody at SAP finds time to get this working out-of-the-box with the application router.

      Regards,

      Wolfgang

      Author's profile photo Gregor Wolf
      Gregor Wolf

      Thank you Wolfgang for asking this question! Matthieu hope you find time to give an answer here.

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Wolfgang, Wolfgang,

      a colleague is finalizing a tutorial that exactly demonstrate it. I will add the link here as soon as it's available.

      Best,

      Matt

      Author's profile photo Meesum Kirmani
      Meesum Kirmani

      Any updates on this front?

       

      Author's profile photo Tobias Mitter
      Tobias Mitter

      Hi there,

      same opinion as last post from Wolfgang. It does not make sense for me to implemenent this over and over again, especially for simple UI5 applications that just need to connect to an on-premise ODATA Service and have no application logic layer in the cloud.

      In the neo environment, this also works out of the box and is handled by the ui5 application container runtime. There we just deploy the ui5 app and it works.

      Would it be possible to replace this layer with api management? Can it do something like that?

      Regards,

      Tobias

      Author's profile photo mayank saxena
      mayank saxena

      Hello  Matthieu,

      Thanks for this amazing blog series. I have a question here. I am planning to achieve the same thing with ES5 Odata url and UI5 Module.  I have created the approuter app and able to see the login page. It means that configuration of xuaa and approuter is fine. But I did not understand , how the rest of the part could be done for simple HTML5 module. When I am creating the html5 module , wizard created a mta.yaml file but what should be content of this file apart from module information. As I am not adding the Java module how to replace the Java related stuff from UI5 point of view.

      Author's profile photo Micha Günther
      Micha Günther

      Hey there,

      I have a problem creating an instance of the destination service. I can easily create a connectivity service, but if I want to create a destination service I always get this error message:

      Can somebody help me?

      Best Regards,

      Micha

      Author's profile photo Anil Kumar Yanamandra
      Anil Kumar Yanamandra

      Hey ,

      Your org doesn't seem to have entitlements. You need to get Quota Assigned to your Global Account and then in edit the entitlements in the Cloud Platform cockpit to add the Entitlements to the sub account(Org)

      Regards,

      Anil

       

      Author's profile photo Marcus Schiffer
      Marcus Schiffer

      Hi,

       

      is there something similar for Python ?

      I was trying to set up the destination and calling it from python, but failed.

      Cloud connector is available and the destination and connectivity instance is also createdd.

      But how would I call the CC from Python now ?

      any help appreciated.

       

       

      Author's profile photo Gini Hu
      Gini Hu

      Hi,

      Have you solved your issue? I encounter the same issue as you.

      Thank you!

      Author's profile photo Marcus Schiffer
      Marcus Schiffer

      Hi,

       

      here is my solution, however not really good programming but works...

      import os
      from cfenv import AppEnv
      from flask import Flask, flash, redirect, render_template, request, session, abort
      import json
      import traceback
      import requests as rqt
      import datetime
      import Crypto.PublicKey.RSA as RSA
      import python_jwt as jwt
      from hdbcli import dbapi
      from sap import xssec

      import requests # http://docs.python-requests.org/en/master/
      import psutil # https://pypi.python.org/pypi/psutil
      import time, sys, platform
      from requests.auth import HTTPProxyAuth

      output = ""

      app = Flask(__name__)
      env = AppEnv()
      port = int(os.getenv("PORT", 9009))
      uaa_service = env.get_service(name='yourUAAServicehere').credentials

      @app.route('/')
      def cloud_conn():
      if 'authorization' not in request.headers:
      abort(403)
      # No authorization at all

      client = rqt.session()
      access_token = request.headers.get('authorization')[7:]
      security_context = xssec.create_security_context(access_token, uaa_service)
      isAuthorized = security_context.check_scope('yourAppsScopehere')

      output = security_context.get_email()
      if not isAuthorized:
      abort(403)
      # not the right scope in role
      svcs_json = str(os.getenv("VCAP_SERVICES"))
      svcs = json.loads(svcs_json)
      # now we have the service parameters
      secret = svcs["xsuaa"][0]["credentials"]["clientsecret"]
      uaa_url = svcs["xsuaa"][0]["credentials"]["url"] + "/oauth/token"
      uaa_url_auth = svcs["xsuaa"][0]["credentials"]["url"] + "/oauth/authorize"
      # now we know the XSUaa URLs and the password
      clientsec = svcs["connectivity"][0]["credentials"]["clientsecret"]
      clientid = svcs["connectivity"][0]["credentials"]["clientid"]
      opph = svcs["connectivity"][0]["credentials"]["onpremise_proxy_host"]
      oppp = svcs["connectivity"][0]["credentials"]["onpremise_proxy_port"]
      # now we have all connectivity service parameters
      # here we could use xssec.request token for client , is better
      url_proxy = opph + ":" + oppp
      client.get(uaa_url_auth)
      # thats needed to get the XSRF token per get request from the /auth URL from the UAA servive
      if 'X-Uaa-Csrf' in client.cookies:
      csrftoken = client.cookies['X-Uaa-Csrf']
      # here the token is
      else:
      return("kein csrf : " + str(client.cookies))
      client_auth = requests.auth.HTTPBasicAuth(clientid, clientsec)
      # sets the authorization parameters to the header to call the uaa service to set the SSO data for the connectivity service

      try:
      retval = client.post( url=uaa_url, headers={'accept':'application/json', "X-CSRF-TOKEN": csrftoken },
      params= { 'grant_type':'client_credentials','client_id':clientid},
      auth=client_auth)
      # calls the uaa service to get the params granted by the uaa service to authorize against the connectivity service
      except Exception as e:
      strtext = traceback.format_exc()
      return(strtext)
      token = json.loads(retval.content)['access_token']
      # thats the bearer token for authorizing to the connectivity service
      sap_auth = requests.auth.HTTPBasicAuth(str(os.getenv("sapuser")), str(os.getenv("sappassword")))
      # thats the authorization for the SAP system via CC
      url_cc = "yourCloudconnectorURLgoeshere?$format=json"
      # url to CC as stated in the virtual host names in CC config
      proxyDict = { "http" : url_proxy }
      headers = {
      'content-type': "application/json",
      'Proxy-Authorization': "Bearer " + token,
      'cache-control': "no-cache"
      }
      # proxy authorization by bearer token retrieved from post request to uaa service with connectivity user / pass
      try:
      response = client.get( url_cc, proxies=proxyDict, headers=headers, auth = sap_auth)
      # call the cloud connector URL via proxy (from connectivity, with proxy auth) with sap auth
      rs = json.loads(response.text)
      return render_template('test.html',output = output ,sapuser = str(os.getenv("sapuser")), name=security_context.get_given_name(),orders=rs['d']['results'])

      except Exception as e:
      strtext = traceback.format_exc()
      return(strtext)

      return "Ups"
      if __name__ == '__main__':
      app.run(host='0.0.0.0', port=port)

      Author's profile photo Gini Hu
      Gini Hu

      Hi Marcus,

      Finally I connected to my service successfully. Your code helps a lot! 🙂

      Thank you very much for your help!

      Best regards,

      Gini

      Author's profile photo parthibaraja vijayan
      parthibaraja vijayan

      Hi,

      Any idea about the issue in the screen shot?

      This is happening while checking the connection of the CF destination configured.

      Note : Cloud connector configuration is successful for the on-premise system, CF sub-account is successfully added in CC.

      BR,

      Parthibaraja

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Hi Parthibaraja,

      The button "Check connection" works today only for cloud destinations, not for on-premise destinations. So this is actually a bug 😉 This will be fixed soon.

      Best,

      Matt

      Author's profile photo parthibaraja vijayan
      parthibaraja vijayan

      Hi Matt,

       

      Thanks for the info. This does not mean that On-Premise connectivity does not work. It simply means that the Check button is not working and I can proceed with the Nodejs app development consuming on premise oData service as explained in the below blog.

      https://blogs.sap.com/2018/10/16/call-sap-cloud-platform-cloud-foundry-destinations-from-your-node.js-application/

       

      Please advise.

       

      Regards,

      Parthibaraja

      Author's profile photo Matthieu Pelatan
      Matthieu Pelatan
      Blog Post Author

      Exactly! Only the button doesn't work right now for on-premise checks. This is the reason why, it's should not be visible 😉

      Author's profile photo parthibaraja vijayan
      parthibaraja vijayan

      Hi Matt,

      We have gone ahead with the development following the below blog written by Maria .

      https://blogs.sap.com/2018/10/16/call-sap-cloud-platform-cloud-foundry-destinations-from-your-node.js-application/

      We are facing below issue when we run the project.

      Can't Connect to Service Layer
      { Error: getaddrinfo ENOTFOUND s7h s7h:8000
          at errnoException (dns.js:50:10)
          at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)
        code: 'ENOTFOUND',
        errno: 'ENOTFOUND',
        syscall: 'getaddrinfo',
        hostname: 's7h',
        host: 's7h',
        port: '8000' }
      
      
      Any idea about this error ?
      
      Regards,
      Parthibaraja
      Author's profile photo Gini Hu
      Gini Hu

      Hi Matthieu ,

      Is there a Python example? I'm trying to call a web service in on-premise system from cloud foundry. But it tells:

      NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f05fb039f60>: Failed to establish a new connection: [Errno -2] Name or service not known'

      I guess a on-premise destination is needed.

       

      Thanks and best regards,

      Gini

      Author's profile photo Chirag Poddar
      Chirag Poddar

      Hi,

      Has anyone been able to get the application router using "npm config set @sap:registry https://npm.sap.com/" and "npm install @sap/approuter"

       

      I have been unsuccessful using CLI. Get the error

      openssl config failed: error:02001003:system library:fopen:No such process
      openssl config failed: error:02001003:system library:fopen:No such process

       

      Any leads here?

       

      Thanks,

      Chirag

      Author's profile photo Christian Kolbowski
      Christian Kolbowski

      Hi,

      working for me without problems.

      Not sure about your error message, I succeeded the following way:

      Execute via CLI: npm config set @sap:registry https://npm.sap.com

      Check your .npmrc file for the following entry (file might be hidden in your user folder, alternatively print file contents with npm get config):

      @sap:registry=https://npm.sap.com

      Check whether repository is accessible via

      npm search @sap/approuter

      Now npm install @sap/approuter --save should download the package.

       

      Hope that helps.

      Christian

       

      Author's profile photo Ferry Djaja
      Ferry Djaja

      I guess the sharepoint link is expired. Can I have the link to the source code?

      Author's profile photo Erico Oliveira
      Erico Oliveira

      Hi  Matthieu

      Do you know if it is already possible to use JCO (rfc) On-Premise with cloud foundry?

      I have tried a the Tutorial: Invoke ABAP Function Modules in On-Premise ABAP Systems.

      But it does not work, the JCo lib in maven does not exist (pom.xml) and I can not test my connection by the test button.

      In the NEO environment it is OK, but in Foundry NO.

      Could you pass me some documentation of how I can in my java application connect with my On-Premise server via RFC.

       

      Thank you

      Author's profile photo Jonathan Gross
      Jonathan Gross

      My frontend app is written in reactjs and not in java.

      I am trying to use the app router together with my frontend application. But the app router does not direct the user to my frontend application. I tried with a nodejs server app instead of a frontend, and it is ok, it is called after the user logged in in the app router. But if my app is a reactjs frontend, the app router does not direct to it. I guess it is because it wants a server, and not a browser based application. But then I do not understand how to access my frontend application and for my frontend application to have the credentials to call the destinations.

      I would appreciate if someone could provide some support on my issue.

      Thank you very much.

      Author's profile photo Roger Liu
      Roger Liu

      I just want to call Odata service or SOAP from my Spring boot controller, how can I do, please advise. I directly use virtual host but httpclient replied me unkown host error.

      Author's profile photo Neil Prince
      Neil Prince

      Hi

      The code link has expired again. Is it possible to reactivate or maybe add to a git repository instead?

      Regards

      Neil

      Author's profile photo Sombir Singh
      Sombir Singh

      Hi Matthieu,

      On-premise system is accessible after installing on certificate on my local machine using HTTPS protocal only. So we have configured on-premise system in cloud connector using HTTPS protocol.

      But when we try to access resources using destination instance it throw error "HTTP Error 404. The requested resource is not found"

      Jut to verify our code we have created local server (http://localhost:4040) and configured as on-premise system using HTTP protocol in cloud connector, we are able to access resources from this server.

       

      But same code is not working when we try to access resources from first on-premise system which configured using HTTPS protocol in SCC.

      Below is the code for your reference, please let me know is there any other configuration required in case to access HTTPS on-premise system through cloud connector.

       

       

       

      const request = require('request');
      const xsenv = require('@sap/xsenv');
      /***
      * Extract client id, client secret and url from the bound Destinations service VCAP_SERVICES object
      *
      * when the promise resolves it returns a clientid, clientsecret and url of the token granting service
      *
      * @returns {Promise<any>}
      */
      async function getXsuaaCredentials() {
      return new Promise(function(resolve) {
      const xsuaaCredentials = xsenv.getServices({
      xsuaa: {
      tag: 'xsuaa'
      }
      }).xsuaa;
      console.log("getXsuaaCredentials xsuaaCredentials: ")
      console.log(xsuaaCredentials)
      resolve(xsuaaCredentials);
      });
      }

      async function getDestinationCredentials() {
      return new Promise(function(resolve) {
      const destinationCredentials = xsenv.getServices({
      destination: {
      tag: 'destination'
      }
      }).destination;

      console.log("getDestinationCredentials destinationCredentials: ")
      console.log(destinationCredentials)
      resolve(destinationCredentials);
      });
      }

      async function getConnectivityCredentials() {
      return new Promise(function(resolve) {
      const destinationConnectivity = xsenv.getServices({
      connectivity: {
      tag: 'connectivity'
      }
      }).connectivity;

      console.log("getConnectivityCredentials destinationConnectivity: ")
      console.log(destinationConnectivity)
      resolve(destinationConnectivity);
      });
      }

      async function getJwtAuthToken(destAuthUrl, clientId, clientSecret) {
      return new Promise(function(resolve, reject) {
      // we make a post using x-www-form-urlencoded encoding for the body and for the authorization we use the
      // clientid and clientsecret.
      // Note we specify a grant_type and client_id as required to get the token
      // the request will return a JSON object already parsed
      request({
      url: `${destAuthUrl}/oauth/token`,
      method: 'POST',
      json: true,
      form: {
      grant_type: 'client_credentials',
      client_id: clientId
      },
      auth: {
      user: clientId,
      pass: clientSecret
      }
      },
      function(error, response, body) {
      if (error) {
      reject(error);
      } else {
      console.log("createToken body: ")
      console.log(body)
      resolve(body.access_token);
      }
      });
      });
      }

      async function getDestination(access_token, uri, destinationName) {
      return new Promise(function(resolve, reject) {
      // Note that we use the uri and not the url!!!!
      request({
      url: `${uri}/destination-configuration/v1/destinations/${destinationName}`,
      method: 'GET',
      auth: {
      bearer: access_token,
      },
      json: true,
      },
      function(error, response, body) {
      if (error) {
      console.error(`Error retrieving destination ${error.toString()}`);
      reject(error);
      } else {
      console.log("getDestination body: ")
      console.log(body)
      resolve(body.destinationConfiguration);
      }
      });
      });
      }

       

      async function userAuth(url, jwtToken1, jwtToken2, clientId, ClientSecret, hostname, port) {
      return new Promise(function (resolve, reject) {
      let loginModel = {
      "tenancyName": "Default",
      "usernameOrEmailAddress": "eygds",
      "password": "eygds123456"
      }
      var proxyUrl = "http://" + hostname + ":" + port;
      console.log("proxyUrl")
      console.log(proxyUrl)
      console.log("API end point:")
      console.log(`${url}/`)
      var proxiedRequest = request.defaults({'proxy': proxyUrl});
      proxiedRequest({
      method: 'POST',
      url: `${url}/api/account/authenticate`,
      rejectUnauthorized: false,
      headers:{
      "SAP-Connectivity-SCC-Location_ID":"ITP_CF_1",
      "Content-Type":"application/json",
      "Accept": 'application/json',
      "Authorization":"Bearer "+jwtToken1,
      "Proxy-Authorization":"Bearer "+jwtToken2
      },
      json: loginModel
      }, function(error, response, body) {
      if (error) {
      console.log(error);
      console.error(`while executing execution user auth API ${error.toString()}`);
      reject(error);
      } else {
      console.log(`Received response from user auth api`);
      console.log(body)
      resolve(body);
      }
      })
      });
      }

      function userAthentication() {
      return new Promise(async (resolve, reject) => {
      let xsuaaCredentials = await getXsuaaCredentials();
      let xsuaaUrl = xsuaaCredentials.url;

      let destinationCredentials = await getDestinationCredentials();
      let clientIdDest = destinationCredentials.clientid;
      let clientSecretDest = destinationCredentials.clientsecret;
      let uri = destinationCredentials.uri;
      let jwtToken1 = await getJwtAuthToken(xsuaaUrl, clientIdDest, clientSecretDest);
      let destInfo = await getDestination(jwtToken1, uri, 'itc-dest');
      let destinationUrl = destInfo.URL;

      let connectivityCredentials = await getConnectivityCredentials();
      let clientidConn = connectivityCredentials.clientid;
      let clientSecretConn = connectivityCredentials.clientsecret;
      let proxyHostConn = connectivityCredentials.onpremise_proxy_host;
      let proxyPortConn = connectivityCredentials.onpremise_proxy_http_port;
      let jwtToken2 = await getJwtAuthToken(xsuaaUrl, clientidConn, clientSecretConn);

      let loginApiInfo = await userAuth(destinationUrl, jwtToken1, jwtToken2, clientidConn, clientSecretConn, proxyHostConn, proxyPortConn);

      resolve({loginApiInfoRes : loginApiInfo});

      });
      }

      userAthentication();

      Author's profile photo Florian Krupa
      Florian Krupa

      Hello !

      First of all, thanks for the tutorial!

      Sadly the link to the code example isnt working anymore.

      Could we get an update on that?

      Thanks!