cancel
Showing results for 
Search instead for 
Did you mean: 

SAP Cloud SDK Javascript, Client Credential Flow

TobiT
Participant
0 Kudos

Dear community,

I would like to programmatically access the api of the xsuaa and do some automatic configuration bejond the xs-security.json.

Therefore I thought using the Cloud SDK Javascript seems like a good idea.

Currently I am stuck, because the framework is not requesting an auth token.

This is what i am doing:

import { RoleCollectionsApi } from "./clients/AuthorizationAPI";
const xsenv = require('@sap/xsenv');

// load credentials
xsenv.loadEnv();
var service = xsenv.filterServices({ name: 'test-xsuaa-apiaccess' });

(async () => {
    const credentials = service[0].credentials;
    const destination: any = {};
    destination.authentication = "OAuth2ClientCredentials";
    destination.tokenServiceUrl = credentials.url + "/oauth/token";
    destination.clientId = credentials.clientid;
    destination.clientSecret = credentials.clientsecret;
    destination.url = credentials.apiurl
    const responseData = await RoleCollectionsApi.getRoleCollections().execute(destination);
})();
And it will result in:
Error: `AuthenticationType` is "OAuth2ClientCredentials", but no auth tokens could be fetched from the destination service.
I would like to emphasize that I want a technical access to the xsuaa api, i do not need the router.What am i missing?BR,Tobi
0 Kudos

Hi Tobias,

you are using xsenv which is not the SAP Cloud SDK for JavaScript (the SDK uses it as a dependency though). Maybe this article in the documentation of the SDK will help: https://sap.github.io/cloud-sdk/docs/js/guides/how-to-retrieve-jwt

Best regards

Florian

TobiT
Participant

Hi florian.richter2,

i am using the cloud skd:

const responseData = await RoleCollectionsApi.getRoleCollections().execute(destination);

You link did not help me. The last section might be a starting point: https://sap.github.io/cloud-sdk/docs/js/guides/how-to-retrieve-jwt#obtain-jwt-programmatically

The Cloud SDK is unable to generate JWT itself and use it for requests against an API?

Cheers.

Accepted Solutions (1)

Accepted Solutions (1)

Hello together,

there are multiple ways to get this working. First a short explanation. The SDK aims to make it easy for users to consume services, so in general you do not have to extract credentials or fetch tokens. This is all done by the SDK (and the destination service). If you provide a destination object it will not do any fetching or adjustments and use the destination as is - hence the error.

In most use cases you maintain a destination in the destination service and just pass the destination name to the `execute` call. This is also what gregor.wolf is referring to. This will work when you put the clientID, secret and so on in the destination. You could also use the `serviceToken` method of the SDK to fetch a token and build a destiantion with token, url.

For core services of the BTP this is not needed as described here: https://sap.github.io/cloud-sdk/docs/js/features/connectivity/destination#service-binding-environmen...

You just pass the name of the service in the `execute` and a clientCredentialsGrant is fetched and the URL is taken from the VCAP enviorment as well. Unfortunately we missed the XSUAA (was not aware this service has also a API), but this PR adds it: https://github.com/SAP/cloud-sdk-js/pull/2734/

TL:DR your options are:

- Wait until PRs is merged and use canary version of the SDK or wait a week for the next release.

- Create a destination in the destination service and pass the destination name

- Fetch a token manually and create a destination containing the token and url

Best

Frank

0 Kudos

PR is merged and SDK is released already last week so you should be able to to just use the service name and the rest is done by the SDK.

Best

Frank

TobiT
Participant
0 Kudos

Thank you!

Answers (1)

Answers (1)

gregorw
Active Contributor

I would suggest to get a destination created by this section in the mta.yaml:

  - name: your-app-destination-content
    type: com.sap.application.content
    requires:
      - name: your-app-uaa-apiaccess
        parameters:
          service-key:
            name: your-app-uaa-apiaccess-key
    parameters:
      content:
        subaccount:
          destinations:
            - Authentication: OAuth2ClientCredentials
              Name: your-app-uaa-apiaccess
              ServiceInstanceName: your-app-uaa-apiaccess
              ServiceKeyName: your-app-uaa-apiaccess-key
          existing_destinations_policy: update
    build-parameters:
      no-source: true

A destination is much easier to consume in the Cloud SDK or with CAP.

TobiT
Participant
0 Kudos

Thanks Gregor.

Thats weird. I run 1 to n landscapes per subaccount. This will cause collisions.

Does the Cloud SDK work with the "destination" environment variable? I would try this as a workaround.

Cheers

gregorw
Active Contributor
0 Kudos

Instead of "subaccount:" you can also use "instance:". I hope you know that it is not a best practice to mix landscapes in one subaccount. Especially as the Cloud Connector can be only connected to the subaccount you would need to rename which destinations are used in your app.

0 Kudos

Please see my comment below how what is the most convenient way to consume internal services.

Best

Frank