cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

ABAP connect with Microsoft Graph API in cloud

paulThink180
Explorer
0 Likes
3,805

Hello SAP developers,

So the problem I am trying to solve involves connecting to MS Graph API in ABAP (cloud foundry) where the classes are slightly different to normal on-premise systems.
I can connect to open APIs in ABAP cloud that don't require authentication, many examples online of this, however not what I need.

How do you connect using refresh tokens and client secret using abap cloud, and finally display the payload in a z-table? Do you use destinations or is it better to set it all manually in the abap class/program?

I have already been through the following;

OAuth Credentials
https://help.sap.com/docs/CP_CONNECTIVITY/cca91383641e40ffbe03bdc78f00f681/4e1d742a3d45472d83b411e14...

Destination connection in abap cloud from BTP
https://developers.sap.com/tutorials/abap-environment-external-api.html#237e1bf4-668e-4c95-871e-4258...

SAP BTP and Azure integration
https://blogs.sap.com/2021/07/08/sap-btp-integration-with-microsoft-azure/

Connect MS Graph to Destination in BTP
https://blogs.sap.com/2020/10/12/consuming-microsoft-365-api-in-the-cloud-application-programming-ca...

Consume REST API in ABAP Cloud
https://blogs.sap.com/2020/10/27/consuming-rest-apis-with-cloud-abap/

Also, this connection in POSTMAN works fine, can see the payload no worries and all the data I need. So from the Azure side it is set-up fine.

Thanks so much,

Paul

View Entire Topic
gregorw
SAP Mentor
SAP Mentor

Hi Paul,

I don't get why you try to implement your own OAuth client. Haven't you tried the HTTP Communication via Destination Service (Deprecated)? Even if it's deprecated it seems to be the solution working out of the box. Please use this destination template: MicrosoftGraph, adjust it with your Tenant and Client ID. Then import it into your BTP Subaccount where the ABAP Environment is provisioned to. I've tried that in my Free Tier ABAP Environment. Not sure if it would work in BTP Trial.

Then try this Code:

CLASS zcl_ms_graph DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_ms_graph IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    DATA lo_http_destination TYPE REF TO if_http_destination.
    DATA lo_http_client     TYPE REF TO if_web_http_client.
    DATA lo_http_response   TYPE REF TO if_web_http_response.

    TRY.
        " create HTTP destination by cloud destination
        lo_http_destination = cl_http_destination_provider=>create_by_cloud_destination(
            i_name = 'MSGraph'
            i_authn_mode = if_a4c_cp_service=>service_specific ).

        " create HTTP client by HTTP destination
        lo_http_client = cl_web_http_client_manager=>create_by_http_destination( lo_http_destination ).

        " adding header fields
        lo_http_client->get_http_request( )->set_header_fields(
          VALUE #( ( name = if_web_http_header=>content_type value = if_web_http_header=>accept_application_json )
                   ( name = if_web_http_header=>accept       value = if_web_http_header=>accept_application_json ) ) ).

        " request users - would be great if the path would be added to the URL provided in the service
        lo_http_client->get_http_request( )->set_uri_path(
            i_uri_path = '/beta/6f8c8b13-6c5b-42e2-8a42-e4ef99e7ff48/users' ).

        " execute HTTP GET-request and store response
        lo_http_response = lo_http_client->execute( if_web_http_client=>get ).

        " print response text to console
        DATA(ls_status) = lo_http_response->get_status( ).
        out->write( |Response is: { ls_status-code } { ls_status-reason }.| ).
        out->write( lo_http_response->get_text( ) ).

      CATCH cx_http_dest_provider_error cx_web_http_client_error INTO DATA(lx_error).
        " display error details
        out->write( lx_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

The output I've got in the console was:

Response is: 200 OK.
{"@odata.context":"https://graph.microsoft.com/beta/$metadata#users","value":[{"id":"b6815529

Two Question to florian.wahl:

  1. Unfortunately lo_http_client->get_http_request( )->set_uri_path( path ) does not append this to the URL defined in the destination. How could this be achieved?
  2. I did setup a Communication Arrangements with the Scenario ID SAP_COM_0276 (SAP Cloud Platform Destination Service Integration). But I don't understand based on the documentation HTTP Communication via Communication Arrangements how I can specify my BTP Destination.
  3. As the Microsoft Graph is an OData V4 Service would it be possible to use the OData Client?

Best Regards
Gregor

paulThink180
Explorer

Thanks Gregor,

This was an excellent response and fixed our issue. The oData is coming through now with a 200 success code, the problem was in our destination set up. This was why I originally abandoned it and tried to hard code in all in abap steampunk.

Turns out our destination had some sort of bug in it. Even though we set it up identical to yours, one of the errors I was getting in the console was that the Token Service URL Type was not set to dedicated. Even though it was. I exported the destination config and compared it to yours and could see the difference. I then remade a new destination importing your one from github, changed the clientID and secret etc. works perfectly!

thanks so much