Skip to Content
Technical Articles
Author's profile photo Shlomi Lachmish

Execute [OAuth2 client credentials] protected REST request with SAP CAP Application

Hi CAP developers,

I needed to connect a CAP application to a remote oAuth2 client credentials service. 

Here is a short recipe 🧑‍🍳 that describes the steps I made

Ingredients:

  1. package.json
  2. src/rest.cds
  3. src/rest.js
  4. SAP BTP destination service
  5. default-env.json
  6. cds bind destination

Prerequisites:

of course you should have the connection details of the remote service 🤷‍♂️

For this recipe to work you will need the following connections details (we will come back to these props in step 4):

  • Token Service: a url that ends with /token e.g.https://the.oauth.services.url/oauth2/api/v1/token
  • OAuth Setup: grant_type = client_credentials
  • Client ID: <Your CLIENT ID>
  • Client Secret: <Your CLIENT SECRET>
  • Service API: <Url link of the remote rest api service you are trying to connect>

Preparations:

1. In package.json under cds/requires add your new rest connection, for example:

"cds": {
    "requires": {

  …

      “remoteServiceWithOAuth":{

        "kind": "rest",

        "credentials": {

          "destination": “remoteServiceWithOAuth",

          "requestTimeout": 30000

        }
     }
}

2. Create srv/rest.cds file:

for each api endpoint you wish to connect you need to create a function or an action described in a cds file (in this example I use rest.cds but you can name it as you wish)
Please note that CAP expects no surprises, you should declare the exact object props and types for each function or action you use.

for example assume that I have function to GET todos list, and action to POST a new todo item, so my rest.cds would look like:

service RemoteRestService {

    function getTodos() returns array of {

        userId: Integer;

        id: Integer;

        title: String;

        completed: Boolean;

    };

    action createTodo(userId: Integer, title: String, completed: Boolean) returns {

        userId: Integer;

        id: Integer;

        title: String;

        completed: Boolean;

    }; 

}

3. Create srv/rest.js file:

As you probably know our CAP framework uses convention over configuration. So for the implementation part we just need to create the same file name just with .js extension. for example:

class RemoteRestService extends cds.ApplicationService {
    init(){
        this.on('getTodos', async (req) =>{
            const restApi = await cds.connect.to("remoteServiceWithOAuth") //should match the connection name in step 1
            return restApi.tx(req).get("/todos")
        })
        this.on('createTodo', async (req) =>{
            const restApi = await cds.connect.to("remoteServiceWithOAuth")
            return restApi.tx(req).get("/todos", req.data)
        })
    }
}

module.exports = {RemoteRestService}

4. Now you need to login to your SAP BTP CF space and if you don’t have a destination service bind to your cap service you need to create one. Now create a new destination configuration with the following props:

Name: remoteServiceWithOAuth (should match the destination in step 1)
Authentication: OAuth2ClientCredentials
Token Service URL: (as described in prerequisite part 👆)
URL: Service API (as described in prerequisite part 👆)
Client ID: (as described in prerequisite part 👆)
Client Secret: (as described in prerequisite part 👆)
Token Service User: in my case I used the same as my Client ID
Token Service Password:in my case I used the same as my Client Secret

 

That’s it! Now once you deploy to your BTP CF space you should be able to consume you CAP application with the remote rest services 🤘

💡Tip for local development (step 5-6):
In case you want the remote REST to be accessible for your local development as well, you can do it by the following steps:

5. Create /default-env.json file in the project root
    ⚠️ – sensitive data, remember to add this file to .gitignore
    Copy the value of VCAP_SERVICES to our default-env.json file

    How to get your “VCAP_SERVICES” environment variable:
   On command line:
   cf env <myappname>

  Or, by using SAP BTP Cloud cockpit:
  Navigate to the details screen of the deployed app
  In the left menu pane click on ‘’Environment Variables”

Cloud%20cockpit

6. Create a service key for your destination service (from SAP BTP CF UI or by using cli :

cf create-service-key <yourDestinationService> <YourDestinationServiceKey)

Then run the following CDS bind command:
cds bind destination --to <yourDestinationService>:<YourDestinationServiceKey>

That’s it 🎉 now you should be able to run: cds watch --profile hybrid and access your remote destination service 

Reference & Credit:

https://blogs.sap.com/2021/07/30/executing-simple-rest-requests-with-sap-cap-applications/ – consume REST from CAP with no authentication

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Szymon Sanocki
      Szymon Sanocki

      Great, thank you for this post! Published just few days before I went through same case and it works smoothly 🙂