Consuming Cloud Foundry / BTP Services (CAP, Build Process Automation APIs, etc.) from ABAP Cloud with SAML OAuth


Hello Community,

I’m writing this blog to talk about consuming Cloud Foundry APIs (like CAP services or Build Process Automation APIs) from ABAP Cloud. Let me share a bit about why I’m writing this: recently, I had to figure out how to use Build Process Automation APIs in ABAP and it took me a few days to understand the correct Grant Type to use.

Regarding ABAP on-premise, an incorrect approach is attempting to consume Build Process Automation / Workflow APIs using the “Authorization Code” option configured through transaction OA2C_CONFIG. If you follow this approach, you won’t be able to complete the redirect process after confirming the prompt with Login and Password due to the well-known error “The redirect_uri has an invalid domain”.

The correct solution is explained wonderfully in this blog post “Consuming a Business Technology Platform service from an S/4 HANA system using SM59 destination with OAuth.” by Mani P S

Instead of using the “Authorization Code” option in OA2C_CONFIG, the “SAML2.0 Bearer Assertion.” is used.

This method allows the user context to be passed without prompting the user to enter login details but propagating the user via a SAML Assertion.

The “magic” happens in the RFC Destination SM59, specifically in the “OAuth Settings” under the “Logon & Security” tab.

 

If you’re dealing with an ABAP on-Premise scenario consuming the API via SM59, you can follow the steps in the previously mentioned blog. But if you’re working in an ABAP Cloud scenario, keep reading.

This blog aims to explain a similar scenario but within the context of ABAP Cloud.

So in this blog, we’re going to explore how to consume a SAP Build Process Automation APIs for retrieving User Task Instances https://api.sap.com/api/SPA_Workflow_Runtime/path/get_v1_task_instances

The same process can also be applied to consume an API exposed by a CAP service, for instance, or any other Cloud Foundry service.

2.1 SAML Attributes from the Subaccount of the service we want to consume

I won’t go into the details of IDP topics. Let’s consider a scenario where we have two different subaccounts: in my case, a BTP ABAP Environment and another subaccount for SAP Build Process Automation.

First of all, we have to download the SAML Metadata in the Subaccount of the service we want to consume. This procedure is already well described in the “ABAP On-Premise” Blog that I mentioned earlier.

Open the XML, we need a couple of attributes:

the value of entityID will be our “SAML Audience” (1)

Search “AssertionConsumerService” and locate bindings:URI: the Location will be our “Token Service Url” (2)

2.2 ABAP Cloud SAML Metadata

From the Fiori App “Communication System” , click to “Own System” to identify the details of the current ABAP system

In General → Technical Data we can download the SAML Metadata

Now we can set the BTP ABAP as SAML Assertion Issuer in the BTP “Target” Subaccount (the subaccount with the service we want to consume)

in “Trust Configuration” → “New Trust Configuration” and upload the ABAP SAML Metadata

 

2.3 Communication Artifacts

Now we can create the communication artifacts in the BTP ABAP Environment.

2.3.1 An Outbound Service (HTTP Service)

2.3.2 A Communication Scenario

  • select the OAuth 2.0 with SAML 2.0 Bearer Assertion Grant Type
  • add the previously Outbound Service created
  • Click Publish Locally

 

2.3.3 A Communication System (in Fiori Launchpad)

First of all, locate the Credential key from the service we want to consume in the “target” subaccount:

retrieve the Url (3), client id (4) and client secret (5).

Define a new System with the hostname of the API we want to consume

in my scenario:

spa-api-gateway-bpi-eu-prod.cfapps.eu10.hana.ondemand.com Port 443

In Outbound OAuth 2.0 Client Settings:

  • Auth. Endpoint is the url (3) retrieved from the service key adding “/oauth/authorize”
  • Token Endpoint is the Token Service Url (2) (that one with the “alias”)
  • Audience is the SAML Audience (1)

Users For Outbound: Configure a new Outbound User with OAuth 2.0 and client id (4) + client secret (5) based on the service we want to consume (in our case from the build process automation instance)

 

2.3.4 A New Communication Arrangement (in Fiori Launchpad)

select the Communication System we created and all the relevant data will be retrieved

 

2.4 Get User Task Instances

In My Build Process Automation Inbox There are 2 Tasks

 

we are going to consume the API using the Communication Arrangement we defined,

here the ABAP code

  METHOD if_oo_adt_classrun~main.
    TRY.
        DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement(
                                 comm_scenario  = 'Z_BPA_WF_API_COMM_SCENARIO'
                                 service_id     = 'Z_BPA_WORKFLOW_API_REST'

                               ).
        DATA(lo_http_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
        DATA(lo_request) = lo_http_client->get_http_request( ).

        lo_request =  lo_request->set_uri_path( 'public/workflow/rest/v1/task-instances').


        DATA(lo_response) = lo_http_client->execute( i_method = if_web_http_client=>get ).
        DATA(lv_json_results) = lo_response->get_text( ).
        out->write( lv_json_results ).

      CATCH cx_root INTO DATA(lx_exception).
        out->write( lx_exception->get_text( ) ).
    ENDTRY.
  ENDMETHOD.

 

and we can verify that tasks are retrieved

 

2.5 Approve a Task

Now we can try to approve a task using the PATCH method of the same API passing the task instance ID.

Here the ABAP code consuming the API using the same Communication Arrangement but changing the path and the http method.

 METHOD if_oo_adt_classrun~main.
    TRY.

        DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement(
                                 comm_scenario  = 'Z_BPA_WF_API_COMM_SCENARIO'
                                 service_id     = 'Z_BPA_WORKFLOW_API_REST'

                               ).
        DATA(lo_http_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
        DATA(lo_request) = lo_http_client->get_http_request( ).

        "Task ID to approve hardcoded for blog purposes only
        DATA(lv_task_id) = '7b78f908-6eb7-11ee-9204-eeee0a83b6de'.

        lo_request =  lo_request->set_uri_path( 'public/workflow/rest/v1/task-instances/' && lv_task_id ).
        lo_request->set_content_type( 'application/json' ).

        "payload hardcoded for blog purposes only
        lo_request->set_text( '{ "status" : "COMPLETED" , "decision" : "approve" }').

        DATA(lo_response) = lo_http_client->execute( i_method = if_web_http_client=>patch ).
        DATA(lv_json_results) = lo_response->get_text( ).
        out->write( lv_json_results ).

      CATCH cx_root INTO DATA(lx_exception).
        out->write( lx_exception->get_text( ) ).
    ENDTRY.
  ENDMETHOD.

 

After the execution I have only one task in “My Inbox”

in the BPA Monitor we can verify that the task was approved and the user was correctly propagated

 

A question for the community

By the way, to make the discussion more engaging: how can I test Build Process Automation APIs from Postman? considering I don’t want to use client credentials because especially for api like inbox or decisions, testing the api with the propagation of the user is relevant and I don’t have the possibility to set Redirect URIs in the XS-Security.json like a CAP service.

If you know of any workarounds or have ideas, please share them in the comments because I haven’t found a solution.

 



Source link

Be the first to comment

Leave a Reply

Your email address will not be published.


*