cancel
Showing results for 
Search instead for 
Did you mean: 

Trigger SCP from ABAP program

sankar_bhatta
Participant

Hello Experts,

I am triggering a SCP workflow from ABAP system. Below is my code. I am able to get the CSRF token value successfully. But the actual instance creation is not happening I am getting 403 Forbidden error

Note: i am able trigger the instance using postman. so the workflow itself is working fine.

this is my code

*&---------------------------------------------------------------------*
*& Report Z_TRIGGER_SCP_WORFKLOW
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT Z_TRIGGER_SCP_WORFKLOW.
DATA: lo_http_client TYPE REF TO if_http_client.
DATA: response TYPE string.
"create HTTP client by url
"API endpoint for API sandbox
CALL METHOD cl_http_client=>create_by_url
 EXPORTING
 url = 'https://bpmworkflowruntimeXXXXXea-XXXXX.hana.ondemand.com/workflow-service/rest/v1/xsrf-token'
 IMPORTING
 client = lo_http_client
 EXCEPTIONS
 argument_not_found = 1
 plugin_not_active = 2
 internal_error = 3
 OTHERS = 4.
IF sy-subrc <> 0.
 "error handling
ENDIF.
"setting request method
lo_http_client->request->set_method('GET').
"adding headers
lo_http_client->request->set_header_field( name = 'X-CSRF-Token' value = 'Fetch' ).
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Authorization' value = 'Basic XXXXXXXXXXXXXXXXXXXXX' ).
"API Key for API Sandbox
*lo_http_client->request->set_header_field( name = 'APIKey' value = 'Vw0jBxyASfBvXXXXXXXFbEpcTKxizWKr' ).
"Available Security Schemes for productive API Endpoints
"Basic Authentication, OAuth 2.0
"Basic Auth : provide username:password in Base64 encoded in Authorization header
"lo_http_client->request->set_header_field( name = 'Authorization' value = 'Basic <Base64 encoded value>' ).
CALL METHOD lo_http_client->send
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 http_invalid_timeout = 4
 OTHERS = 5.
IF sy-subrc = 0.
 CALL METHOD lo_http_client->receive
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 OTHERS = 5.
ENDIF.
IF sy-subrc <> 0.
 "error handling
ENDIF.
data: lt_fields type TIHTTPNVP.
data(lo_response) = lo_http_client->response.
lo_response->IF_HTTP_ENTITY~GET_HEADER_FIELDS( CHANGING fields = lt_fields ).
*cl_demo_output=>display( lt_fields ).
data(ls_fields) = lt_fields[ name = 'x-csrf-token' ].
data(lv_csrf) = ls_fields-value.
CALL METHOD cl_http_client=>create_by_url
 EXPORTING
 url = 'https://bpmworkflowruntimeaXXXXXX-XXXXX.hana.ondemand.com/workflow-service/rest/v1/workflow-instances'
 IMPORTING
 client = lo_http_client
 EXCEPTIONS
 argument_not_found = 1
 plugin_not_active = 2
 internal_error = 3
 OTHERS = 4.
IF sy-subrc <> 0.
 "error handling
ENDIF.
"setting request method
lo_http_client->request->set_method('POST').
"adding headers
lo_http_client->request->set_header_field( name = 'X-CSRF-Token' value = lv_csrf ).
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Authorization' value = 'Basic XXXXXXXXXXXXXXXXXXXXX' ).
CONCATENATE '{"definitionId": "myworkflowtest",'
 '"context": { "PreqItem": "00010", "Material": "000000000000000011",'
 '"Plant": 5000, "DelivDate": 25082018,"PrNumber": " " }}' into data(lv_json).
CALL METHOD lo_http_client->request->set_cdata
 EXPORTING
 data = lv_json.
CALL METHOD lo_http_client->send
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 http_invalid_timeout = 4
 OTHERS = 5.
IF sy-subrc = 0.
 CALL METHOD lo_http_client->receive
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 OTHERS = 5.
ENDIF.
IF sy-subrc <> 0.
 "error handling
ENDIF.
response = lo_http_client->response->get_cdata( ).
cl_demo_output=>display( response ).

Accepted Solutions (1)

Accepted Solutions (1)

qmacro
Developer Advocate
Developer Advocate

It looks like you're not passing any cookies between the calls. Cookies contextualise the token that's fetched. Without them, you'll get a 403. See this Q&A for more details. https://answers.sap.com/questions/563171/why-the-business-rules-invoke-rule-service-need-co.html Cheers!

PS you also had your userid and password more or less in plain sight - in the Basic Authentication header, encoded with Base64 (which is simple to decode). So I replaced some of the characters with Xs to obscure it for you.

sankar_bhatta
Participant

Hi DJ,

Thanks for the hint. By adding the cookie handling it is working now.

Answers (2)

Answers (2)

Sesh_Sreenivas
Product and Topic Expert
Product and Topic Expert

Hi Sankara,

Like DJ mentioned, you need to use the cookies while calling the API to create workflow instance. You can refer to the following links for the source code and explanation:

https://archive.sap.com/discussions/thread/3786067

https://blogs.sap.com/2017/08/04/regarding-cookie-manipulation-in-cl_http_client-to-avoid-csrf-token...

Regards,

Sesh

sankar_bhatta
Participant
0 Kudos

Hi Sesh,

After making changes to consider cookies, the code works fine. I am pasting the code below so that it will help others. one question that I have.

- What is the best way in this case to create hoop client?. is it by create_by_url or create_by_destiantion? in first case we have to enter basic authentication in base64 format, but in other case we can create a SM59 ( type G ) destination and use that.

DATA: lo_http_client TYPE REF TO if_http_client.
DATA: response TYPE string.
data: lt_fields type TIHTTPNVP.
data: lt_cookies type TIHTTPCKI.<br>
"create HTTP client by url<br>
 CALL METHOD cl_http_client=>create_by_url
 EXPORTING
 url = 'https://bpmworkflowruntimXXXXXXx.hana.ondemand.com'
 IMPORTING
 client = lo_http_client
 EXCEPTIONS
 argument_not_found = 1
 plugin_not_active = 2
 internal_error = 3
 OTHERS = 4.<br><br><br>
IF sy-subrc <> 0.
 "error handling
ENDIF.
data: l_query type string.
l_query = '/workflow-service/rest/v1/xsrf-token'.<br>
 CALL METHOD cl_http_utility=>set_request_uri
 EXPORTING
 request = lo_http_client->request
 uri = l_query.
"setting request method
lo_http_client->propertytype_accept_cookie = if_http_client=>co_enabled.<br>
lo_http_client->request->set_method('GET').<br>
"adding headers
lo_http_client->request->set_header_field( name = 'X-CSRF-Token' value = 'Fetch' ).
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Authorization' value = 'Basic XXXXXXXXXXU2XXXXXX' ).<br><br>
"Available Security Schemes for productive API Endpoints
"Basic Authentication, OAuth 2.0<br>
"Basic Auth : provide username:password in Base64 encoded in Authorization header
"lo_http_client->request->set_header_field( name = 'Authorization' value = 'Basic <Base64 encoded value>' ).<br>
CALL METHOD lo_http_client->send
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 http_invalid_timeout = 4
 OTHERS = 5.<br>
IF sy-subrc = 0.
 CALL METHOD lo_http_client->receive
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 OTHERS = 5.
ENDIF.<br>
IF sy-subrc <> 0.
 "error handling
ENDIF.<br>
data(lo_response) = lo_http_client->response.
response = lo_http_client->response->get_cdata( ).
lo_response->IF_HTTP_ENTITY~GET_HEADER_FIELDS( CHANGING fields = lt_fields ).<br>
data(ls_fields) = lt_fields[ name = 'x-csrf-token' ].
data(lv_csrf) = ls_fields-value.<br>
 lo_http_client->response->get_cookies( CHANGING cookies = lt_cookies ).<br>
l_query = '/workflow-service/rest/v1/workflow-instances'.
 CALL METHOD cl_http_utility=>set_request_uri
 EXPORTING
 request = lo_http_client->request
 uri = l_query.<br><br><br>
IF sy-subrc <> 0.
 "error handling
ENDIF.<br>
"setting request method
lo_http_client->request->set_method('POST').
lo_http_client->propertytype_accept_cookie = if_http_client=>co_enabled.
"adding headers
lo_http_client->request->set_header_field( name = 'X-CSRF-Token' value = lv_csrf ).
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Authorization' value = 'Basic XXXXXXXXXTXXXXXXXX=' ).<br>
LOOP AT lt_cookies ASSIGNING FIELD-SYMBOL(<cookie>).
 lo_http_client->request->set_cookie( name = <cookie>-name
 value = <cookie>-value ).
 ENDLOOP.<br>
CONCATENATE '{"definitionId": "myworkflowtest",'
 '"context": { "PreqItem": "00010", "Material": "000000000000000011",'
 '"Plant": 5000, "DelivDate": 25082018, "Quantity" : 13, "PrNumber": " " }}' into data(lv_json).<br><br><br>
CALL METHOD lo_http_client->request->set_cdata
 EXPORTING
 data = lv_json.<br>
CALL METHOD lo_http_client->send
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 http_invalid_timeout = 4
 OTHERS = 5.<br>
IF sy-subrc = 0.
 CALL METHOD lo_http_client->receive
 EXCEPTIONS
 http_communication_failure = 1
 http_invalid_state = 2
 http_processing_failed = 3
 OTHERS = 5.
ENDIF.<br>
IF sy-subrc <> 0.
 "error handling
ENDIF.<br>
response = lo_http_client->response->get_cdata( ).
cl_demo_output=>display( response ).
vamsixk
Active Participant
0 Kudos

with SM 59 you can safely store your User ID and password . if you use URL, you have to pass the user id and password as indicated earlier by DJ Adams.

so the best practice would be to use the SM59 approach.

Kind Regards,

Vamsi