cancel
Showing results for 
Search instead for 
Did you mean: 

ABAP connect with Microsoft Graph API in cloud

paulThink180
Explorer
0 Kudos
1,522

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

Accepted Solutions (1)

Accepted Solutions (1)

gregorw
Active Contributor

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

Answers (3)

Answers (3)

hobru
Active Participant
0 Kudos

So the problem is connecting from Steampunk, right? I have not tried this yet, but since you are saying the calls are working from Postman you have already figured out all the steps for the "authentication dance".

Can you share more insights on where you are facing the problems? Are some of your HTTP calls going through? Are you able to connect to any other external API that requires authentication?

- Holger.

paulThink180
Explorer
0 Kudos

Hi Holger,

thanks for replying. So today I managed to get some success however I am having trouble getting the access token into a variable that I can use for the actual header request to MS Graph and get the data I need.
I am doing 2 calls, one for the token, then one to use that token to get the data. I have moved away from BTP destinations and instead am hard coding a destination in steampunk using if_web_http_client and then setting the header and form-fields using variables from postman.

See screen shots, first 2 are from postman where I can get the access token fine with the 4 main form values (clientID, clientSecret grant-type and scope). I can call this as many times as I like and I get a new token. Also, the second screenshot shows that the token will work successfully to get the data I need. Again, this is in postman and I need this to be done in steampunk.

I do get a 200 code return in my abap console output when I use if_web_http_client->get_headers() however the if_web_http_client->get_text() does not show the token, therefore I cannot use the response for the next call in the header to get the actual data I need.

This is where I am stuck?

Token GET in postman - working.

GET user entity request in postman - working

paulThink180
Explorer
0 Kudos

And this is what I am trying to do in steampunk, see console output. Can't see the token, therefore can't make the data request to MSGraph

gregorw
Active Contributor
0 Kudos

I haven't noticed that you're using Steampunk in my initial response. Have you tried to follow HTTP Communication via Communication Arrangements?

paulThink180
Explorer
0 Kudos

Yes, funny you mention that, we are currently looking through that option now to see if it helps with making the API call in cloud-foundry. Will update here if we have any success.
I guess another option is to use on-premise to do the API calling to MSGraph, then use cloud connector to link up with our steampunk environment?

gregorw
Active Contributor
0 Kudos

Going from a Cloud Solution to On Prem to call a Cloud Solution sould not be the way to go. Maybe hobruche can get the right people involved here.

gregorw
Active Contributor
0 Kudos

Are you aware of the ABAP SDK for Azure?

paulThink180
Explorer
0 Kudos

Hi Gregor,

Yes, I have looked through your posts on this topic, we didn't pursue as it looked like you needed the SAP GUI. Do you know if there is a way to use ABAP SDK for Azure using the Cloud BTP?

We will try the SDK on our 2020 on premise system to see how it goes but our deployment is in the cloud foundry. Otherwise SDK would have been perfect for us.

Unless I am missing something?