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


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


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.
  • 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>


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

"cds": {
    "requires": {



        "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 {
        this.on('getTodos', async (req) =>{
            const restApi = await"remoteServiceWithOAuth") //should match the connection name in step 1
            return restApi.tx(req).get("/todos")
        this.on('createTodo', async (req) =>{
            const restApi = await"remoteServiceWithOAuth")
            return restApi.tx(req).get("/todos",

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”


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: – consume REST from CAP with no authentication

Assigned Tags

      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 🙂


      Author's profile photo Mariam Id-Manssour
      Mariam Id-Manssour


      Thanks for this great blog post I was looking exactly about the same thing using Basic authentication.


      Author's profile photo Rufat Gadirov
      Rufat Gadirov

      Hi @Shlomi Lachmish,


      thank you for this very useful blog!

      I followed your steps and cds bind worked as well. It is just that I get the following error during my http request (locally from BAS):

      statusCode: 502,
      reason: {
      message: 'Error during request to remote service: \n' +
      'Failed to load destination. Caused by: No binding to an XSUAA service instance found. Please make sure to bind an instance of the XSUAA service to your application.',

      I already have bound my application against xsuaa and the service instance is active with a corresponding key. Do you possibly have any idea?

      BR & Thank you

      Author's profile photo Rufat Gadirov
      Rufat Gadirov

      Ok, I have found a solution: 🙂

      This section helped me:

      BAS CLI command:

      cds bind -2 bookshop-uaa

      This adds an auth section containing the binding and the kind xsuaa to the .cdsrc-private.json file. This file is created if it doesn't exist and keeps the local and private settings of your app:


        "requires": {
          "[hybrid]": {
            "auth": {
              "kind": "xsuaa",
              "binding": { ... }

      The rest based http request worked afterwards!