cancel
Showing results for 
Search instead for 
Did you mean: 

Calling OAuth2 protected APIs from a SAPUI5 application on SCP CF using the Destination service

ssimsekler
Active Contributor
0 Kudos

Hello

We have APIs exposed in i) SAP API Management and ii) in another API Gateway. The APIs need authentication via OAuth2 and/or API Key. From an SAPUI5 application, we would like to consume these APIs.

I have defined three destinations:

Northwind Destination

External API destination with OAuth2ClientCredentials

OAuth2 Token retrieval destination

The app router config, i.e. xs-app.json. Here, I have two routes per destination trying to see if keeping UAA instance make any difference. One variant, i.e. ending with "uaa", has "authenticationType": "xsuaa", the other variant has "authenticationType": "none".

{
 "welcomeFile": "/index.html",
 "authenticationMethod": "route",
 "logout": {
 "logoutEndpoint": "/do/logout"
 },
 "routes": [
 {
 "authenticationType": "xsuaa",
 "csrfProtection": false,
 "source": "^/northwinduaa/(.*)$",
 "destination": "northwindodatav2",
 "target": "$1"
 },
 {
 "authenticationType": "none",
 "csrfProtection": false,
 "source": "^/northwindnone/(.*)$",
 "destination": "northwindodatav2",
 "target": "$1"
 },
 {
 "authenticationType": "xsuaa",
 "csrfProtection": false,
 "source": "^/externalapiuaa/(.*)$",
 "destination": "externalapi",
 "target": "$1"
 },
 {
 "authenticationType": "none",
 "csrfProtection": false,
 "source": "^/externalapinone/(.*)$",
 "destination": "externalapi",
 "target": "$1"
 },
 {
 "authenticationType": "xsuaa",
 "csrfProtection": false,
 "source": "^/externalapitokenuaa/(.*)$",
 "destination": "externalapitoken",
 "target": "$1"
 },
 {
 "authenticationType": "none",
 "csrfProtection": false,
 "source": "^/externalapitokennone/(.*)$",
 "destination": "externalapitoken",
 "target": "$1"
 },
 {
 "source": "^(.*)$",
 "target": "$1",
 "service": "html5-apps-repo-rt",
 "authenticationType": "xsuaa"
 }
 ]
}
Northwind API calls are executed successfully:
var aData = jQuery.ajax({
 type: "GET",
 contentType: "application/json",
 url: "northwinduaa/V2/Northwind/Northwind.svc/Customers",
 dataType: "json",
 async: false,
 success: function (data, textStatus, jqXHR) {
 alert("Success to post. Success callback.");
 }
 }) 

The call to the external API with OAuth2ClientCredentials fails with HTTP 500 "Internal Server Error":

var aData = jQuery.ajax({
 type: "POST",
 contentType: "application/json",
 url: "externalapiuaa/RESTful/json/Search",
 dataType: "json",
 async: false,
 data: JSON.stringify(oAPISearchObject),
 success: function (data, textStatus, jqXHR) {
 alert("Success to post. Success callback.");
 }
 }) 

The call to external API's token retrieval endpoint fails with HTTP 403 - Forbidden although debugging the API in SAP API Management, I can see the API is hit and access token is generated.

var aData = jQuery.ajax({
 type: "POST",
 contentType: "application/x-www-form-urlencoded",
 url: "/externalapitokenuaa",
 timeout: 0,
 async: false,
 data: oOauthTokenRetrievalPayload,
 success: function (data, textStatus, jqXHR) {
 alert("Success to post. Success callback.");
 }
 }) 

The API does not need API Key. "odata_gen" was used as WebIDEUsage so that Business Application Studio could see these destinations; but it wasn't much help as there is no convenience feature for generating code for this use case. And the above requests test OK with Postman.

After this long post, can I ask if anyone has an idea why the API calls are failing. Is there a sample application which showcases this scenario, i.e. accessing OAuth2 protected APIs from SAPUI5 where credentials are kept secure by the Destination service?

Kind Regards

Accepted Solutions (0)

Answers (3)

Answers (3)

sucheno
Participant
0 Kudos

Hi serdar.simsekler,

Did you try using Authentication as OAuth2JWTBearer for External API destination ?

It should automatically manage the JWT based for all calls via this destination based on the provided client ID, secret and token service URL configuration

I am not sure about OAuth2 Token retrieval destination, If you you are using this to get the token explicitly via separate service call from UI to pass to above destination, You might consider to remove it if above destination works. If you still need this destination, you might try OAuth2JWTBearer authentication as well.

Regards,

Suchen.

ssimsekler
Active Contributor
0 Kudos

So, we figured the main problem was the OAuth2 token generation service. It seems the token generation service needs to return access token, expiry and token type. Ours was missing the token type, i.e.:

{
...
"token_type": "Bearer"
}

Now, strangely, the app works in local; but, when we deploy to the SCP subaccount, the calls to the destination fails returning 404. So, if anyone can provide an input for this part that would be great.

ravinsi4
Explorer
0 Kudos

Hi Serdar,

Were you able to fix this issue? I am also trying to execute same scenario. Could you please guide how did you implement it.

Regards

Ravindra

raeijpe
Contributor
0 Kudos

I believe you are missing to authenticate to the Cloud Platform in your call to retrieve the external API's token from SCP. You specify that the endpoint uses XSUAA. This means that you should be authenticated to the SCP and this is the reason why you will get a 403.

So if your UI5 application already authenticates to the SAP Cloud Platform (deploy your ui5 application on SCP), you should add the cookie (in the HTTP header) with your AJAX call.

Else you should implement the authentication to SCP upfront. You can do this using Basic Authentification info in the HTTP Header (only for development) or implement the SAML2 flow.

If your application is running as App (compiled code), you can also implement a OAuth flow.

Depending on your SCP from you can generate a OAuth Client Key (NEO) or use the ClientId and Client Secret provided by the Service Key of the Destination Service (CF)

ssimsekler
Active Contributor
0 Kudos

Hi r.eijpe

Thanks for your response. The users authenticate to the SCP subaccount when they launch the frontend application. Then the API authentication is supposed to happen through the destination service where we found the problem (I added as an answer to this post). However, as mentioned there, it seems we can make it work in local; but, it does not work when the application is deployed to the SCP subaccount.

raeijpe
Contributor
0 Kudos

Hi Serdar,

As mentioned in my response before, did you specify the authentication header information in your AJAX call. The user can authenticate to the SCP subaccount when they launch the frontend application, but in that case, you also need to add the access token (properly as a cookie in the UI5 response) as the HTTP header of your AJAX call.

If you already did this, can you explain how you deploy the application? If you are using an MTA descriptor, you maybe can try to use the setting forwardAuthToken: true as explained in the documentation

Kind regards,

Robert