Skip to Content
Technical Articles
Author's profile photo Carlos Roggan

SAP Cloud Platform Backend service: Tutorial [27]: API: called: from: external: easier

This blog is part of a series of tutorials explaining the usage of SAP Cloud Platform Backend service in detail.

This blog is like an appendix:
We learned how to call API from REST client tool (e.g. Postman)
It is complicated, due to OAuth flow
So we learned a lot if interesting things around OAuth:
What is OAuth? And “Authorization Code” ?
How to call my API from node.js application?
And more

In all those great blogs we learned how to do the manual steps to overcome the OAuth protection
That was good learning – and we got used to it and it is OK

Now I’d like to propose an alternative: use App Router
Deploy Application Router which routes to Backend service API
It is easy, just requires 3 little files

Advantage: App Router handles the OAuth flow for us (we need only Basic Authentication)
Disadvantage: Some effort to configure and deploy App Router (it is easy)

To learn about App Router you can follow my little series: part 1 and part 2 and part 3
In this blog we’re just doing the required steps:

Create App Router, redirecting to Backend service, facilitating calls from REST client

Prerequisites

Some APIs created in SAP Cloud Platform Backend service and you user has role to access them
You might need node.js installed on your machine, including configured SAP registry (see here)

Preparation

We’re going to create an application and deploy it to Cloud Foundry
This application wraps the App Router
It needs to be bound to an instance of XSUAA
That instance needs to contain the scope required by Backend service

To create such instance, see here
Note:
For the present tutorial, we don’t need to create Service Key

In our example, we use the following name for the XSUAA service instance:
“XsuaaForAppRouterWithBs”

Create App Router Configuration App

Create application structure

On your local file system, create files and folders like shown below

– C:\dev\app
– manifest.yml
– C:\dev\app\approuter
– package.json
– xs-app.json

Configuration

manifest.yml

---
applications:
- name: ApprouterToBackendservice
  host: tobs
  path: approuter
  memory: 128M
  services:
  - XsuaaForAppRouterWithBs
  env:
    destinations: >
      [
          {
              "name": "backendservice_v2",
              "url": "https://backend-service-api.cfapps.eu10.hana.ondemand.com/odatav2/DEFAULT/",
              "forwardAuthToken": true
          },
          {
              "name": "backendservice_v4",
              "url": "https://backend-service-api.cfapps.eu10.hana.ondemand.com/odatav4/DEFAULT/",
              "forwardAuthToken": true
          }
      ]

Explanation:
We create a destination pointing to the root URL of an OData v2 service in Backend service
A second destination is meant for v4 services
In both cases, App Router does the OAuth flow and forward the access token to Backend service
Furthermore, we define a binding to an existing XSUAA instance called “XsuaaForAppRouterWithBs”
If you’re using an XSUAA instance with different name, you need to adapt the name
We define a short host: tobs, because our app is only used to redirect to Backend service
If you get an error during deployment, make sure to change the host to some unique name

xs-app.json

{
  "authenticationMethod": "route",
  "routes": [
    {
      "authenticationType": "basic",
      "csrfProtection": false,
      "source": "^/bsv2/(.*)$",
      "target": "$1",
      "destination": "backendservice_v2"
    },
    {
      "authenticationType": "basic",
      "csrfProtection": false,
      "source": "^/bsv4/(.*)$",
      "target": "$1",
      "destination": "backendservice_v4"
    }
  ]
}

 

Explanation:
We define a route which points to the v2 root URL. To access this, route, we define a short URI-segment bsv2 (points to Backend service, OData V2 services)
That entry point requires “only” “Basic Authentication”
Furthermore, the x-csrf-token is not required (usually it is)
Similar configuration for OData V4 services

package.json

{
  "name": "myapprouter",
  "scripts": {
    "start": "node node_modules/@sap/approuter/approuter.js"
  },
  "dependencies": {
    "@sap/approuter": "^6.0.1"
  }
}

Explanation:
Our app is a node.js app.
It is described by the package.json file
In the package.json file we declare a dependency to the existing default App Router module.

We declare: when our app is started, the javascript file to be executed is the approuter.js, to be found in the existing approuter module
Means, our app does nothing than start the existing approuter, with our configuration

Note:
The version will probably change in future, so make sure to update it, if deployment fails
To update, run npm install –save

Download App Router

Actually, downloading the App Router is not necessary.
The approuter is a node module which will be installed via npm in the cloud environment.
As such, we can just deploy the app, as long as it contains the package.json file which tells how to install and run the approuter.
If it works, you don’t need to install node.js on your local machine
If you face dependency errors during deployment, then you need to download/install the approuter module via npm into the application folder, on your local machine.
Only in that case, you need to install node.js on your local machine)

To download approuter, go to command shell, navigate to folder c:\dev\app\approuter
There, execute  the following command:

npm install –save

Deploy the app

Deploy the app to SAP Cloud Platform Cloud Foundry environment, like you’re used to (i.e. command line or cockpit)

Use it

After successful deployment, you have to find the host URL of your app, it is either on the command prompt, or in the app-overview in the cloud cockpit

In my example it is
tobs.cfapps.eu10.hana.ondemand.com

In order to route to our Backend service API, we have to append one of the defined routes (bsv2), followed by the name of our API, as defined in Backend service (in my example PRODUCTSERVICE)
In case of v4 service, we need to add the version parameter(;v=1)

Example URLs:

https://tobs.cfapps.eu10.hana.ondemand.com/bsv2/PRODUCTSERVICE;v=1/
https://tobs.cfapps.eu10.hana.ondemand.com/bsv2/PRODUCTSERVICE;v=1/Products

Other service:

https://tobs.cfapps.eu10.hana.ondemand.com/bsv2/CUSTOMERSERVICE;v=1/

For odata v4, just change the route, e.g.:

https://tobs.cfapps.eu10.hana.ondemand.com/bsv4/PRODUCTSERVICE;v=1/Products

etc

Note:
If you switch from V2 service
https://tobs.cfapps.eu10.hana.ondemand.com/bsv2/PRODUCTSERVICE/
to v4
https://tobs.cfapps.eu10.hana.ondemand.com/bsv4/PRODUCTSERVICE/
you’ll get an error: Invalid URL
The reason is that the version param is required
https://tobs.cfapps.eu10.hana.ondemand.com/bsv4/PRODUCTSERVICE;v=1/

You can execute POST, PATCH, DELETE etc like usual

Even x-csrf-token is not required (at least App Router doesn’t require it and Backend service – currently – either)

Troubleshooting

What to do if you happily deploy everything and try testing and get….. Forbidden ???
See this blog for a Troubleshooting guide

Summary

We want to call our Backend service API from local REST client tool (e.g. Postman)
Instead of fetching OAuth access token, etc, we can do a different approach:

We can app an intermediate App Router in the cloud
That is an app which we have to deploy
That app contains a dependency to the actual App Router which is an existing node.js module
In the app, we configure the App Router such that it redirects to Backend Service
We configure that we can authenticate to our app with “Basic Authentication”
App Router fetches an OAuth access token and forwards it to Backend service

This makes life easier, because now, all APIs can be accessed from REST client without the tedious token-handling

Appendix: XSUAA creation command

If you’re using command line, you’ll find this copy&paste-ready command helpful.
It creates an instance of XSUAA service, with instance name “XsuaaForAppRouterWithBs”

cf create-service xsuaa application XsuaaForAppRouterWithBs -c “{\”xsappname\”:\”XsuaaForAppRouterWithBs\”,\”tenant-mode\”:\”dedicated\”,\”foreign-scope-references\”:[\”$XSAPPNAME(application,4bf2d51c-1973-470e-a2bd-9053b761c69c,Backend-service).AllAccess\”]}”

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Francisco Ferreira
      Francisco Ferreira

      Hi Carlos,

       

      Thank you for your blog series.
      If you wanted to call/integrate the services associated with the products subscribed by the Application in dev portal from an external application (not in SCP) what would be your approach or what would you suggest?

       

      Ps: imagine that i have already the policies that verify the APIKey and generate the authentication Token when a request is made.

      Thanks in advance,

      Best Regards,

      Francisco Ferreira.

      Author's profile photo Carlos Roggan
      Carlos Roggan
      Blog Post Author

      Hello Francisco Ferreira , sorry for the very late reply, I haven't seen your question earler. I'd like to ask you to send me a personal message, to explain more in detail your scenario. If it is a more general achitecture question, please post it in the community as question.
      Kind Regards,
      Carlos