Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Token-based oAuth2 call using authorization code flow (via the SAP OAuth 2.0 client)

georg_w_
Discoverer
0 Likes
15,410

Dear SAP community,

a viewer (web application) is to be called up on our SAP system using a toolbar button. This call should be token-based via oAuth2 using an authorization code flow of the oAuth 2.0 client:

https://help.sap.com/viewer/e815bb97839a4d83be6c4fca48ee5777/7.5.6/en-US/3041aa0be8194960ad02fb6f07d...

The associated oAuth2 nodes in the SICF are activated, an OAuth2.0. Client profile created via the SE80, an OAuth2.0. Client created via transaction OA2C_CONFIG, I have the necessary authorizations, the certificates were stored using STRUSTSSO2, the button in the toolbar of the ALV in the SAP system has been added, but I am currently stuck with the implementation. There are several blog entries that I have already worked through:

· Configuring OAuth 2.0 and Creating an ABAP Program That Uses OAuth 2.0 Client API

· How to Set up an OAuth 2.0 Client Profile in AS ABAP?

An instance of the OAuth 2.0 client is created there via cl_oauth2_client=>create(). Then a token is fetched using lo_oa2c_client->execute_cc_flow (Client Credential Flow) and transferred to the http client.

But my problem is that I would like to start an authorization code flow and the class CL_OAUTH2_CLIENT only offers the possibility to start a SAML 2.0 flow (lo_oa2c_client->execute_saml20_flow) or an update flow (lo_oa2c_client-> execute_refresh_flow). Our SAP_BASIS module has version 7.50 SP22.

Is it true, that there are exactly two ways to authorize the AS ABAP to access the end user's resources by requesting an OAuth 2.0 access token for your service provider:

1. call the grant endpoint with the suitable URL (https://<Hostname>:<Portnumber>/sap/bc/sec/oauth2/client/grant/authorization?profile= ZMY_CLIENT_PROFILE) or

2. use the transaction OA2C_GRANT?

As described here: Requesting an OAuth 2.0 Access Token

So for me there is still the question of how I can call the grant endpoint from my ABAP program - is this a simple HTTP GET request and does anybody know how to do this?

The implementation should be similar to the REPORT zhelloworld in this blog article Access SAP Hana Cloud Platform using the OAuth 2.0 Client API by Joachim Doersam:

REPORT zhelloworld LINE-SIZE 1023.

DATA: profile TYPE oa2c_profile,
target TYPE string,
method TYPE string,
lo_http_client TYPE REF TO if_http_client,
lo_oa2c_client TYPE REF TO if_oauth2_client,
l_status_code TYPE i,
l_response_data TYPE string,
lt_fields TYPE tihttpnvp,
lx_oa2c TYPE REF TO cx_oa2c.

FIELD-SYMBOLS: <ls_field> LIKE LINE OF lt_fields.


START-OF-SELECTION.

profile = 'ZMY_CLIENT_PROFILE'.
target = 'https://helloworld<YourAccount>.hanatrial.ondemand.com/HelloWorld/'.
method = 'GET'.

**********************************************************************
* Create HTTP client
**********************************************************************
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = target
ssl_id = 'ANONYM'
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

lo_http_client->propertytype_logon_popup = 0.

CALL METHOD lo_http_client->request->set_method
EXPORTING
method = method.

**********************************************************************
* Set OAuth 2.0 Token
**********************************************************************
TRY.

CALL METHOD cl_oauth2_client=>create
EXPORTING
i_profile = profile
RECEIVING
ro_oauth2_client = lo_oa2c_client.

CATCH cx_oa2c INTO lx_oa2c.
WRITE: 'Error calling CREATE.'.
WRITE: / lx_oa2c->get_text( ).
RETURN.
ENDTRY.

TRY.

CALL METHOD lo_oa2c_client->set_token
EXPORTING
io_http_client = lo_http_client.

CATCH cx_oa2c INTO lx_oa2c.
TRY.
CALL METHOD lo_oa2c_client->execute_refresh_flow.
CATCH cx_oa2c INTO lx_oa2c.
WRITE: 'Error calling EXECUTE_REFRESH_FLOW.'.
WRITE: / lx_oa2c->get_text( ).
RETURN.
ENDTRY.
TRY.
CALL METHOD lo_oa2c_client->set_token
EXPORTING
io_http_client = lo_http_client.
CATCH cx_oa2c INTO lx_oa2c.
WRITE: 'Error calling SET_TOKEN.'.
WRITE: / lx_oa2c->get_text( ).
RETURN.
ENDTRY.
ENDTRY.

**********************************************************************
* Send / Receive Request
**********************************************************************
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.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

CALL METHOD lo_http_client->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

**********************************************************************
* Display result
**********************************************************************
CALL METHOD lo_http_client->response->get_status
IMPORTING
code = l_status_code.
WRITE / |{ l_status_code }|.

WRITE /.

IF l_status_code = 200.
CALL METHOD lo_http_client->response->get_cdata
RECEIVING
data = l_response_data.

DATA(l_content_type) = lo_http_client->response->get_content_type( ).
IF l_content_type CP 'text/html*'.
cl_demo_output=>display_html( html = l_response_data ).
ELSEIF l_content_type CP 'text/xml*'.
cl_demo_output=>display_xml( xml = l_response_data ).
ELSEIF l_content_type CP 'application/json*'.
cl_demo_output=>display_json( json = l_response_data ).
ENDIF.
ELSE.
CALL METHOD lo_http_client->response->get_header_fields
CHANGING
fields = lt_fields.

LOOP AT lt_fields ASSIGNING <ls_field>.
WRITE: / <ls_field>-name, 25 <ls_field>-value.
ENDLOOP.

ENDIF.

**********************************************************************
* Close HTTP client
**********************************************************************
CALL METHOD lo_http_client->close
EXCEPTIONS
http_invalid_state = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

Best regards,

Georg

1 ACCEPTED SOLUTION
Read only

larshp
Active Contributor
11,873

See SAP note 3041322 - OAuth 2.0 Client: Downport of grant type Client Credentials

See SAP note 3041322 - OAuth 2.0 Client: Downport of grant type Client Credentials

4 REPLIES 4
Read only

larshp
Active Contributor
11,874

See SAP note 3041322 - OAuth 2.0 Client: Downport of grant type Client Credentials

Read only

0 Likes
11,873

Hello Lars,

thank you very much for the hint. The class CL_OAUTH2_CLIENT should have a method lo_oa2c_client->execute_cc_flow to start the Client Credential Flow after applying the correction instruction of the support package. In fact, I haven't tried it, just checked that the prerequisites (kernel 7.53) are met.

Because the implementation should be realized quickly and I didn't know the SAP note yet, I instead executed two HTTP requests via cl_http_client=>create_by_url(), mo_client->send(), mo_client->receive() and mo_client->close( 😞

1) Obtaining a token

2) Calling up the web application

Best regards,

Georg

Read only

0 Likes
11,873

It would probably have been easier to implement using the method lo_oa2c_client->execute_cc_flow

Read only

anandsap
Discoverer
0 Likes
11,873

Hi everyone,

I am in similar situation like above, and have resolved many issues and started working on program to make it work.

I implemented the above note 3041322 and all its dependent notes.

I have tested from OA2C_GRANT_APP and it shows green. Now I want to implement using a program.

Scenario 1:

I tested OA2C_GRANT_APP and before the token is expired, I test my program. This produces the required result and it get the content from share point (my end point is share point here ).

Scenario 2:

I delete the token in OA2C_GRANT_APP simulating a expired token or brand new request for new token. I have followed the program steps as mentioned in similar blogs.

the initial step set_token() raises an exception cx_oa2c_at_not_available, 
so I called execute_cc_flow() ; but this raises an exception CX_OA2C_NOT_ALLOWED. 
Before implementing the note, i tried execute_refresh_flow(), that too didnt work at this step. 
So I tried calling set_token() again which gives me CX_OA2C_AT_NOT_AVAILABLE. 

My question is do we need to keep the initial token generated from the OA2C_GRANT_APP? Does anyone have similar issue in getting response from Sharepoint API or other APIs?