Skip to Content
Technical Articles

Calling Business Technology Platform APIs using Business Application Studio REST Client with OAuth 2.0 authorization flows

Introduction

When developing applications on the SAP Business Technology Platform (BTP) you often come quite naturally to the point, where you want to test certain features via APIs. These might be features in your own application or services provided by the BTP. Until this point I mostly used the Postman API client, because it offers a large amount of features and eases development and testing a lot. As an example, Postman makes it much easier for you to use OAuth 2.0 as an authorization mechanism when calling APIs and even sets the correct HTTP header lines in your request. On the other hand, you might lose a bit of the understanding of what actually happens (unless you check the console).

Recently in my role as an SAP Education Consultant I was working on a new training for SAP Workflow Management and because this is a product on the BTP, most of the development happens in the SAP Business Application Studio (SBAS). As SBAS is a cloud development environment, it is very convenient to use in trainings because participants don’t need the software on their local machines. Also no more annoying WTS session are required, you just work in your browser. This is the point where I stumbled across the issue of not wanting to use Postman, at least in these setups. I want to be able to demonstrate API requests in a lightweight training setup, that is easy to replicate. Fortunately SBAS has an extension that is built-in by default, the REST Client extension. In this post I want to describe some basic features of the REST Client extension based on a SAP Workflow Service API call requiring OAuth 2.0 authorization using both, the Authorization Code grant type and the Client Credentials grant type.

For understanding and getting the OAuth 2.0 Authorization Code flow running, this blog post by Carlos Roggan was very helpful for me.


Scenario

Note: The scenario that I am going to show might sound specific to SAP Workflow Management, but everything in this post is applicable to any scenario, where you want to test API integration with other BTP applications and services.

The SAP Workflow Service offers a large array of API endpoints to manage workflows and tasks. When building your own workflows, you might want to start instances of the workflows for testing purposes. By default this is possible via the Manage Workflows Fiori app. But during development it can be inconvenient to switch to a different UI and to require many extra clicks to get a workflow started. Also in a productive environment workflows will mostly be triggered by other applications like e.g. start UIs. These applications use APIs behind the scenes. So you want to use APIs for testing to be more flexible and to be as close to the final use case as possible. Use SAP API Business Hub to discover SAP APIs and integration options for your scenario.

As the SAP Workflow Service API requires OAuth 2.0 authorization, I want to show how to trigger the API endpoint to start a new workflow instance using the Client Credentials flow and the Authorization Code flow. I will be using the REST Client extension in SBAS in order to be platform independent during development.

The%20Workflow%20Service%20API%20endpoint%20I%20am%20going%20to%20trigger%20in%20SAP%20API%20Business%20Hub

The Workflow Service API endpoint I am going to trigger, found in SAP API Business Hub

SAP Business Application Studio REST Client

As I write this post in an SAP context, I refer to the SAP Business Application Studio REST Client extension, while actually the REST Client is a Microsoft Visual Studio Code (VS Code) extension.

Why does an extension for Microsoft Visual Studio Code work in SAP Business Application Studio?

SAP Business Application Studio is a cloud based development environment based on the Open Source Eclipse Theia IDE. Theia in turn reuses many VS Code technologies, like for example the Monaco code editor and the language server protocol (LSP). Because Theia took VS Code as a role model, it also supports VS Code extensions out of the box.

Do I need to install the REST Client extension in SBAS?

The REST Client extension is built-in by default in your SBAS Dev Space, so no further activation or installation steps are required.

Built-in%20REST%20Client%20extension%20in%20SAP%20Business%20Application%20Studio

Built-in REST Client extension in SAP Business Application Studio

Let me introduce a few of the features of the REST Client extension, that I am going to use:

  • HTTP language support with syntax highlighting
  • Send/Cancel/Rerun HTTP request in editor and view response in a separate pane with syntax highlighting
  • Organize multiple requests in the same file
  • Environments and custom/system variables support

Please refer to the REST Client GitHub Repository for a full list of features and documentation. Disclaimer: Documentation and code provided in this GitHub repository are not owned, maintained or managed by SAP, as this is a third party extension originally developed for Microsoft Visual Studio Code which is compatible with SAP Business Application Studio due to before mentioned reasons.

Getting Started

In my SBAS Dev Space (from where I want to send my API requests), I create a new file with .http or .rest file extension, e.g. WorkflowRequests.http. The REST Client extension will recognize these files and add its features to it, when I am editing them.

Let’s first start building a request for the actual API endpoint that I want to call. I want to implement a POST request to the /v1/workflow-instances endpoint. I can use HTTP syntax to build the request. As base URL I use https://api.workflow-sap.cfapps.eu10.hana.ondemand.com/workflow-service/rest, because my Workflow Service instance is running in the BTP AWS EU10 environment. I add the Content-Type: application/json header, because the endpoint expects a JSON body in the request.

POST https://api.workflow-sap.cfapps.eu10.hana.ondemand.com/workflow-service/rest/v1/workflow-instances HTTP/1.1
Content-Type: application/json

{
    "definitionId": "ourcustomworkflow",
    "context": {
        "ourCostumField": "Some sample data"
    }
}

First%20file%20with%20.http%20extension%20and%20syntax%20highlighting%20by%20REST%20Client

First file with .http extension and syntax highlighting by REST Client

 

As you can see in the screenshot, the REST Client extension highlights the syntax and even adds a Send Request button. Let’s see what happens, when I try to send the request.

HTTP%20401%20response%20because%20of%20missing%20authorization

HTTP 401 response because of missing authorization

Obviously the request fails with a HTTP 401 response, because I did not add any authorization information to the request.

Implementing OAuth 2.0 Authorization Flows

In order to be able to successfully call the Workflow Service API, I need to add authorization details to my requests. The API requires OAuth 2.0 authorization. In the following I will use the Client Credentials flow and the Authorization Code flow. Please refer to IETF rfc6749 and rfc6750 for further details.

Prerequisites

  • SAP Workflow Service (or any other service that you would like to use) instance + service key
  • Following information from the service key uaa property:
    • clientid
    • clientsecret
    • url

Required%20service%20instance%20key%20information

Required service instance key information

Use of REST Client Environments

In order to encapsulate environment related information from the actual HTTP requests, I make use of the environment feature of the REST Client extension. This feature allows me to separate for example development environment credentials from production environment credentials. The environment data can be incorporated into HTTP requests as variables, bracketed by curly brackets: {{variable}}.

You can create an environment in the settings.json file. Find the file using following procedure:

  1. Open path in SBAS: File > Settings > Open Preferences
  2. Search for Rest Client Environment
  3. Click on Edit in settings.json (you can either edit the file for all workspaces of your user or just within a certain workspace)

Within property rest-client.environmentVariables define variables, that should be available across environments in the $shared property and create new properties for new environments that you want to switch (e.g. DEV, PROD etc.). In my case, I edit the file with following properties:

{ 
    "rest-client.environmentVariables": {
        "$shared": {
            "workflowBaseUrl": "https://api.workflow-sap.cfapps.eu10.hana.ondemand.com/workflow-service/rest",
            "authenticationBaseUrl": "https://ibpm00.authentication.eu10.hana.ondemand.com"
        },
        "workflowDev": {
            "clientId": "sb-clone-d4694deb-62a2-455b-99ab-d7e05db21167!b33347|workflow!b10150",
            "clientSecret": "05446cba-8XXX-XXX-XXXX-aaf42f3f47c4$apGt_ux9fv-Y2XXXXXXXXQUieoey991odPNV7ouI_Ps="
        }
    } 
}

Now I can make use of the variables in my .http file.

Client Credentials Flow

In this flow, I request an OAuth access token using client credentials. The client in this case is the service instance that was created for the respective BTP service.

I need to request the access token from the /oauth/token endpoint of the authenticationBaseUrl using the client credentials that I previously extracted from the Workflow Service key. I create the following HTTP request in my .http file:

### OAuth access token request with client credentials
# @name client_credentials_grant
POST {{authenticationBaseUrl}}/oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id={{clientId}}&client_secret={{clientSecret}}

Note how the variables defined in the settings.json are incorporated into the request. In the second line, you find an annotation # @name client_credentials_grant. This annotation gives us the possibility to refer to the corresponding response using variable client_credentials_grant , after the request has been sent.

Let’s test the request. If everything was set up correctly, the response should look like the following:

Access%20token%20response%20with%20Client%20Credentials%20Flow

Access token response with Client Credentials Flow

The body contains a property access_token, which contains the OAuth access token. Now I need to use this access token in my previously created Workflow Service API request in an Authorization header. The term Bearer must precede the token. It should look like following:

### Start new workflow instance
POST {{workflowBaseUrl}}/v1/workflow-instances
Content-Type: application/json
Authorization: Bearer {{client_credentials_grant.response.body.access_token}}

{
    "definitionId": "ourcustomworkflow",
    "context": {
        "ourCostumField": "Some sample data"
    }
}

Note how I made use of the client_credentials_grant variable that I created via the annotation in the access token request. In total, my WorkflowRequest.http file now looks like following:

Retrieve OAuth access token and use it for authorization

Now let’s try to trigger the Workflow Service API endpoint again. If you received the access token in the previous request, your service instance has the required scopes to start a workflow instance and the workflow definition with the specified id exists, a new workflow instance should be created:

Response%20after%20successful%20API%20call

Response after successful API call

Note that the startedBy property shows the client id of the service instance that was used in the OAuth authorization flow. Especially in a workflow scenario this could be undesirable because a workflow should be started on behalf of a certain user and that users identity is required in the workflow itself. For this purpose, let’s have a look at the Authorization Code flow.

Authorization Code Flow

Unfortunately, this flow becomes a bit more cumbersome, because a user is involved that first has to authenticate his-/herself with the underlying Identity and Authentication Service in order to receive an authorization code. The authorization code can then be used to retrieve the OAuth access token.

Retrieve Authorization Code

In order to retrieve an authorization code, I need to build a URL with certain URL parameters. The URL consists of following parts:

  • Base URL: use the authentication base URL previously retrieved from the instance service key
  • URL path for authorization code: /oauth/authorize
  • client_id URL parameter: client id previously retrieved from instance service key. Note:The client id needs to be URL encoded!!
  • response_type URL parameter: code
  • redirect_uri URL parameter: URL that the Identity and Authentication Service redirects the request to, after successful user authentication. The URL will be suffixed with the authorization code in URL parameter code. Note: The redirect URI needs to be URL encoded. When implementing the flow programmatically, the redirect URI should point to a callback endpoint of the client that initiates the authorization code flow, which can then retrieve the code.
  • scope URL parameter (optional): List the application scopes that you want to request with this grant, comma separated

Let’s put it all together:

https://ibpm00.authentication.eu10.hana.ondemand.com/oauth/authorize?client_id=sb-clone-d4694deb-62a2-455b-99ab-d7e05db21167%21b33347%7Cworkflow%21b10150&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080

Note that I set the redirect URI to http://localhost:8080, although I do not have a local server listening on that port. For the purpose of collecting the authorization code in the browser, this works anyways. When entering the URL in a browser, I am asked to authenticate with a user.

Required%20user%20authentication

Required user authentication

Depending on your BTP subaccount settings, you either authenticate with the SAP ID Service or your custom IDP, if configured. In my case it is a custom IDP. After successful authentication I am redirected to the redirect URI and find the authorization code as a URL parameter:

http://localhost:8080/?code=MozQZPK9Wk

In this case, the authorization code is MozQZPK9Wk.

Retrieve OAuth Access Token with Authorization Code

Now I need to implement another HTTP request to retrieve an OAuth authorization code. The request looks like following:

### OAuth access token request with authorization code
# @name auth_code_grant
POST  {{authenticationBaseUrl}}/oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {{clientId}}:{{clientSecret}}

grant_type=authorization_code&code=MozQZPK9Wk&redirect_uri=http%3A%2F%2Flocalhost%3A8080

Note that this time, I use Basic authorization with clientId and clientSecret, the grant_type is authorization_code, I add the authorization code in parameter code and we add the redirect_uri parameter for verification purposes. I need to make sure to not wait too long after retrieving the authorization code to perform this request because it only has limited validity. If everything was ok, we again receive an OAuth access token.

Now when doing the same Workflow Service API request using the access token acquired using the Authorization Code flow, the result looks like following:

Response%20after%20creating%20workflow%20instance%20with%20OAuth%20authorization%20code%20flow%20access%20token

API response after creating workflow instance with OAuth authorization code flow access token

This time the startedBy property shows the user id of the user, that authenticated his-/herself during the OAuth Authorization Code flow. Note that the user needs to have the roles / scopes assigned, that are required for the API endpoint that is being called.


Conclusion

In this post I introduced the SAP Business Application Studio REST Client extension and showcased a scenario, where I called a SAP Workflow Service API for creating new workflow instances. I used the OAuth 2.0 grant types Client Credentials and Authorization Code and pointed out differences in the flows, especially when implementing them with the SBAS REST Client extension.

My conclusion is, that the REST Client extension is a powerful alternative to other rest clients, like for example Postman. It is particularly comfortable, when you are developing applications using the Business Application Studio and you do not want to rely on other tools and software, that need to be installed on your local machine. If you haven’t tried out REST Client yet, I encourage you to do so. In this post, I have only touched a few of the included features.

Since this is my first post in the SAP Community, I would appreciate your feedback and suggestions for improvement in a comment. If you have additional questions use the relevant tag Q&A areas, e.g. SAP Business Application Studio or SAP Workflow Management.

If you are furthermore interested in SAP Workflow Management, have a look at the Workflow Management Community Page and consider our new instructor-led training CLD500, which provides an introduction to SAP Workflow Management and the related BTP services SAP Workflow Service, SAP Business Rules Service and SAP Process Visibility Service.

Resources

Carlos Roggan: SAP Cloud Platform Backend service: Tutorial [15]: Security: using “Authorization Code” Grant

Huachao Mao: REST Client GitHub Repository

Eclipse Foundation, Inc.: Theia IDE

SAP SE: SAP Business Application Studio Documentation

Jonas Helming and Maximilian Koegel: The Eclipse Theia IDE vs. VS Code

Internet Engineering Task Force (IETF): The OAuth 2.0 Authorization Framework and The OAuth 2.0 Authorization Framework: Bearer Token Usage

SAP SE: Workflow Management Community Page

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