Calling Microsoft Graph APIs via Logic Apps with service principals and app permissions

I was doing a piece of work today where I needed to run some API calls against Microsoft Graph APIs to collect and process some information about service accounts (known as service principals in Azure AD parlance). Although there are lots of built in connectors for Logic Apps, there aren't any out of the box connectors for the Microsoft Graph APIs, so to build this integration we currently need to rely on the HTTP connector.

Thankfully, my colleague Tareq Saifi has written this article on the Microsoft Tech Community that explains how to call the Graph APIs using delegated permissions. This was enough to get me started however I hit some issues along the way that I wanted to document, as a note for future me and maybe useful to others too.

The main differences and issues I faced compared to Tareq's blog were:

I'll walk through each of these in turn through the remainder of this post.

Delegated permissions versus Application permissions #

The first thing that was different between what I was attempting to achieve and Tareq's blog is the subtle but important distinction when selecting the permission type when granting appropriate permissions to your service principal (step 1M in the original post) - you can select either delegated or application permissions:

  • Delegated permissions are used by apps that have a signed-in user present. For these apps, either the user or an administrator consents to the permissions that the app requests. The app is delegated with the permission to act as a signed-in user when it makes calls to the target resource.

  • Application permissions are used by apps that run without a signed-in user present, for example, apps that run as background services or daemons. Only an administrator can consent to application permissions.

Due to the nature of the service I was implementing, application permissions were the appropriate selection. This is then where the next issue came up - what permissions do I actually need to grant here?

Which permissions to grant? #

After I had selected application permissions, it wasn't immediately clear to me where find which actions would be authorized in the Graph API when when choosing which permissions to grant (step 1N from original post).

Screenshot of the 'Request API permissions' blade in Azure Active Directory. Microsoft Graph API anbd Application permissions are selected in the blade. A list of potential permissions are listed below. The list reads: AccessReview, AdministrativeUnit, AgreementAcceptance, Agreement.

The answer lay in the Graph REST API specification. In this example you can see clearly which permissions allow you to call each API, in order of least to most privileged. The next issue was actually a blocker to progress this much further - I had insufficient permission to grant permissions!

Permission to grant permission #

The final hurdle was in granting the permissions to my service principal. Tareq covers this in his blog in step 1O - however this glosses over the fact that not every user has permission to change permissions in your Azure AD tenant. Checking the docs...:

The Azure account must have permission to manage applications in Azure Active Directory (Azure AD). Any of the following Azure AD roles include the required permissions:

  • Application administrator
  • Application developer
  • Cloud application administrator

Unsurprisingly I am not afforded any of these roles in the internal Microsoft AD tenant - so to build this demo I was at a dead end. I worked around this by using a different Azure AD tenant (where I host this site, in fact).

Screenshot of the 'examplegraphapi' service principal in the joeplumb Azure Active Directoy tenant. The screenshot shows the configured permissions for the service principal, which includes 'Application.Read.All' and 'User.Read'.

If I needed to work through this challenge in a tenant where this was a blocker, the solution would be to talk to the administrator of the tenant and agree to sign off on permissions for my App Registration to have the required permissions to perform the operations I needed. This block is here for a reason - a good permissions management strategy is all part of sound security posture.

A small schema change #

The final thing that appears to have changed since the initial post was that the schema for the response from the oauth2/token API was different - for me, it took the following structure:

{
    "properties": {
        "access_token": {
            "type": "string"
        },
        "expires_in": {
            "type": "integer"
        },
        "ext_expires_in": {
            "type": "integer"
        },
        "token_type": {
            "type": "string"
        }
    },
    "type": "object"
}

This was easy to manage with the Use sample payload to generate schema functionality in the Parse json activity.

Screenshot of the 'Parse json' activity in the Logic app designer. The task is taking the body of the response from the HTTP call as an input, and parsing the json response. There is an orange arrow pointing to the 'Use sample payload to generate schema' button.

Further reading #

Conclusion #

I've walked through some of the subtle differences in permission configuration to enable your service principals to interact with the Graph API. I've also highlighted some of the challenges I faced along the way to help accelerate others.

Please message me on Twitter if this has been helpful, or useless, or if you have any questions or comments!