Skip to Content

Introduction

Recently in the community a question was asked how an access token can be determined to access a XSUAA secured SAP HANA XS Advanced service (e.g. written in Node.js) directly from an external application. I think I gave a very detailed answer to that question, but I wanna write it down here also in a blog post, because there are some steps necessary to be able obtain an access token via the XSUAA API. As said in the title, the “Password Grant with Client and User Credentials” method is used and described in the following lines. Details about the API interface can be found in the official Cloudfoundry UAA documentation.

In summary following steps are necessary:

  • Determine client credentials for XS Advanced service application.
  • Determine the XSUAA server URL.
  • Obtain an access token from the /oauth/token endpoint of the XSUAA server.

For test reasons I created a simple MTA application containing an Node.js module with a test endpoint returning a simple JSON object containing a “success” property to indicate that the call was successful.

{
  "success": true
}

The application is secured by an XSUAA service instance. A user who wants to access the endpoint need the scope “Display”. This scope is assigned to my test user via a role collection. In case you want to try it out by yourself you can clone my test repository xsa-access-api-from-external, create the XSUAA service either via CLI or the XSA Cockpit using the xs-security.json file, deploy the test application, create a role collection containing the created roles and assign the role collection to your test user.

In my case I deployed the application to the development space on a HANA express edition instance.

Determine the XSUAA server and the client credentials

Before an access token can be requested it needs to be known where the token can be requested. It is also necessary to know the client id and client secret for the application we deployed before. Both information can be found in the environment variables of the application in following properties:

  • VCAP_SERVICES.xsuaa.credentials.clientid
  • VCAP_SERVICES.xsuaa.credentials.clientsecret
  • VCAP_SERVICES.xsuaa.credentials.url (XSUAA server url which provides the required access token endpoint)

The environment variables for an application can be determined either via the XS CLI or within the XSA Cockpit. Pre-condition: Application is deployed and XSUAA service is bound to the application.

To get the environment variables via the XS CLI for my test application with the name IqdL0TY2Av5-jlbDnal-access-api-js deployed in the development space the XS ENV command is called which produces following output.

In the XSA Cockpit the same information can be found in the Service Bindings area for an application. Marking the XSUAA service binding and pressing “Show sensitive data” displays the required information

Determine access token

After all required information is determined an access token can be requested by doing a POST request to the /oauth/token endpoint for the XSUAA server URL. In that test here the complete URL is http://hxehost:39032/uaa-security/oauth/token.

For test reasons Postman is used to simulate the client. As seen on the next image for the request the following headers have to be set:

  • Accept: set to application/json;charset=utf8 to indicate that the client accepts a JSON response
  • Content-Type: set to application/x-www-form-urlencoded to define that the payload contains form-url-encoded values

The payload of the request needs to have following form-url-encoded values:

  • grant_type: set to password to define that the client and user credentials method has to be used for the token determination
  • username: set user name of authorized user
  • password: password of the authorized user
  • client_id: the client id determined for the application
  • client_secret: the client secret determined for the application
  • response_type: set to token to indicate than an access token is requested

After a successful call with correct user and client credentials an access token is returned in property access_token. The scope property contains also the Display scope (external-api-access.Display = application name + scope) which is assigned to the user via the role collection containing the relevant role.

Positive API access test

With the access token it is possible to access the test API. The test API endpoint is available at end point /api/testEndpoint for the deployed Node.js application. In that case the full URL is https://hxehost:51047/api/testEndpoint. In case you try the example by yourself check the application URL you got either in the XSA Cockpit (application section) or via the XS APPS command.

For the executed GET request again the Accept header is set to indicate that a JSON response is expected. The more important header is the Authorization header which has to be set in form “Bearer <access token>”.

Executing the request will result in getting the expected JSON object.

Negative API access test

To show that the access token really works and is not just a fake the access token in the header is set to something different than the access token provided by the UAA server.  Adding e.g. a “XX” in front of the access token in the header results in a 403 Forbidden result.

Conclusion

I hope this helps a little bit in case someone wanna access an XSA deployed service via an access token from another external application. Please also check the above linked official Cloudfoundry UAA documentation for more details and options.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Mahmoud Kassem

    Hi Florian,

    first off thank you for this blog it is rather hard to find resources about the topic in the XS a context. And as a disclaimer I’m pretty new to this stuff. I followed the flow with our XS advanced application and got an access token in Postman, but I’m unfortunately getting a 403 error:

    {
        "error": "insufficient_scope",
        "error_description": "Insufficient scope for this resource",
        "scope": "uaa.admin uaa.user"
    }

    which I find strange I was assuming that having the $XSAPPNAME.Display scope would suffice.

    I’m also wondering if the xsuaa is the IdP in your scenario, is that even possible? What I’m curious about is wether the username and password that are passed in the POST call also live in the xsuaa or in an exernal IdP(which is our scenario).

    EDIT:

    It is resolved now the issue was actually sitting in front of the computer. I was trying to access the wrong endpoint namely the application router, which requires more scopes. Using the access token to access the js module directly yielded the expected result.  

    (0) 

Leave a Reply