cancel
Showing results for 
Search instead for 
Did you mean: 

How to use OAuth2ClientCredentials in destinations?

bhalchandraswcg
Contributor

Hi

I am protecting SCP Business Rules APIs using OAuth as demonstrated in this blog.

Then, I am trying to access business rules using another destination from UI5.

Since, business rules are now protected by OAuth, I tried to configure destination using OAuth2ClientCredentials authentication type. However, when business rules are invoked from UI5, the call using destination retrieves only 500 Internal Server Error and nothing else. A check connection button on destination returns 'Failure reason: "Could not check at the moment. Please try again later"' error.

Please could you help me with this?

Thank you,

Bala

Accepted Solutions (1)

Accepted Solutions (1)

Ivan-Mirisola
Product and Topic Expert
Product and Topic Expert

Hi Bala,

Excuse me for such a long answer. This topic is quite new and requires some through explanation so you can understand whats going on.

Have you tried performing the same calls via postman?

I have created the oauth client in Cloud Cockpit for a Java Application (just for testing). I understand that BPM/BRM will deploy their end-points as Java applications and will work the same way. The client is created with the "Authorization Grant" type "Client Credentials". With that, you will be able to use "id" as username and "secret" as password for your initial request to:

https://oauthasservices-<subaccount>.hanatrial.ondemand.com/oauth2/api/v1/token?grant_type=client_cr...

This will give you a Bearer Token such as this one:

{
    "access_token": "sjhdgdgasuygdsuygdasuydgsdu",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": ""
}

Once you have this access_token, you can call the actual service end-point by sending the token in the header as:

Authorization: Bearer sjhdgdgasuygdsuygdasuydgsdu

You could also try postman with OAuth v2.0 method. However, I couldn't make the grant type "Client Credentials" work on SCP (maybe because I'm not really that familiar with Postman). I've made it work with Postman using "Authorization Code" grant type instead.

Grant Type: Authorization Code
Callback URL: <your brm endpoint>
Auth URL: https://oauthasservices-<account>trial.hanatrial.ondemand.com/oauth2/api/v1/authorize
Access Token URL: https://oauthasservices-<account>.hanatrial.ondemand.com/oauth2/api/v1/token
Client ID: <44444444-1234-aaaa-bbbb-ffffffffffff>
Client Secret: <password>
Client Authentication: Send as Basic Auth header   <----- this is important

And in the Cloud Cockpit, you need to create an OAuth Client of "Authorization Grant: Authorization Code" for your brm end-point and set Confidential to true. The redirect URL should also be the same as your BRM endpoint.

If the above works in postman, then you are half way there. Before you are able to consume the BRM destination the next step is to implement the BRM service call in Java (as an API proxy) to avoid exposing your OAuth Client IDs, Passwords, etc in your JavaScript code.

Unfortunately, in a Neo environment, the OAuth2ClientCredentials authentication method is currently supported by Java Applications only (perhaps you could use it on XSJS too - am not sure. For sure you could create an XSJS application that fetches the token securely without using the OAuth2ClientCredentials destination authentication method).

The destination service stores data (keys, secrets, etc) in a secure way. However, an HTML5 application will expose the Bearer token anyway, since you need make two requests to load data from your service and this has to be achieved in JavaScript. I believe this is considered a security risk. For this reason, I believe this authentication method ins't allowed for HTML5 applications. Maybe there are plans to have it implemented in the future, I am not the one holding such answer.

Think of OAuth protected services those that will be called on behalf of a business user. In other words it means that your business service (probably an OData service) will perform the call to the BRM to determine a discount for a business user. In such case, you don't really need to have the business user authenticate directly onto the BRM service. Instead, you delegate authentication via OAuth so your OData service implementation can perform the call and return data to the end-user. With that in mind, your UI should be simplified with just calls to the OData service, where business user authentication is really relevant and the destination service will work.

This authentication method is fairly new to both Neo and CF. Therefore you won't find a lot of blogs out there. Even though it is not too hard to develop your own API Java Proxy. Keep in mind that:

1) Class HttpDestination has a pre-configured Apache HttpClient ready to be used and will perform an automatic access token retrieval and caching. So you don't need to create a POST request, retrieve the token and only then access the BRM end-point. All you really need is the destination with the OAuth2ClientCredentials destination authentication method.

2) The ConnectivityConfiguration and AuthenticationHeaderProvider classes will help you to interact with the destination configuration and the header to be sent to your API.

Furthermore, in the past I used to recommend OAuth as an option to protect an API Key in an HTML5 application, which is not really recommend. I've also seen some examples and exercises where fetching the Bearer authentication token via OAuth was done using JavaScript which is exactly what you should avoid anyway - but on such specific cases security was not important.

Hope this helps.

Best regards,
Ivan

bhalchandraswcg
Contributor
0 Kudos

Hi Ivan,

Thank you for shedding light on OAuth2ClientCredentials authentication type in destinations.

I have successfully invoked BRM service using OAuth 2.0 from Postman. Now, my next step is to invoke OAuth 2 protected BRM using destination. I have used UI5 just as example to simplify the question here.

I understand that we may not want to have a call to get OAuth Access token inside UI5 application - this clearly exposes client_secret to anyone who uses the app. However, I did not understand the security risk of invoking a service through destination where the destination uses OAuth2ClientCredentials. Please could you elaborate on the risk.

Thank you,

Bala

Answers (1)

Answers (1)

Ivan-Mirisola
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Bala,

If you use the destination with OAuth2ClientCredentials in the Java Destinations API it all fine. That would be true for any server-side technology.

(I'll clarify the previous answer) The destination plain text stuff I was referring to isn't the secure data that is written within (things you store via Cockpit) but the following specific use-case.

To be able not to hard-code any of the secure stuff (secrets, keys, ids) you need to use one destination to fetch the token (using POST method in an AJAX request with the user/password stored in the destination configured for Basic Authentication) and another to fetch the data (using a destination with no authentication and do a GET with the proper Bearer header variable set with the fetched token).

I'd say this is OK for testing and exercises but very hard to make it really secure. You would have to implemented CSRF protection on the oauth protected resource and set the oauth token to have a really short life (maybe ~10 seconds) - the shortest lifetime on SCP for the oauth client is 1 min. This should not be considered optimal since a clever person can do some real damage in less than 1 min with a "stolen" token. Remember that by hitting F12 one can capture the oauth token by simply inspecting the requests made by the browser.

Best regards,
Ivan