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 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 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 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 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 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:
- Open path in SBAS: File > Settings > Open Preferences
- Search for Rest Client Environment
- 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 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 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-62a...
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 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:
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