Microsoft Graph authentication

  • 16 September 2020
  • 8 replies
  • 464 views

Userlevel 6
Badge +9

This post decribes the required steps to connect to Microsoft Graph webservices (Azure, Office 365, Microsoft 365). Detailed information about Microsoft Graph can be found here: https://docs.microsoft.com/en-us/graph/.

This guide uses Application permissions to get access to the API without a user's credentials. The different types of permissions for Microsoft Graph are explained here.

To access Microsoft Graph using Application permissions, first follow the instructions on this page to configure the app registration, which is required to retrieve an authorization token.

 

Process flow

Once you have setup your app registration in the Azure portal, you can create a process flow to authenticate and call the required services.

In this example we will be using the following process flow, which is triggered by the execution of a task, then uses an HTTP connector to authenticate and get an authorization token, calls a Graph web service using that token, and shows the response of that call. Only the two HTTP connector actions are described here.

Example process flow

 

The process flow uses three process variables, tokenheader and response, all of type nvarchar(max).

 

HTTP connector: Authenticate

The authentication process action retrieves an authorization token required to access the web service.

 

Input

The input parameters of the process action should be configured like this:

Input parameter Assignment Value
URL Constant value https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
HTTP method Constant value POST
Content-Type Constant value application/x-www-form-urlencoded
Content Constant value client_id={client id}
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret={client secret}
&grant_type=client_credentials

The tenantclient id and client secret for the registered app can be found in the Overview and Certificates & secrets pages of the Azure portal.

Example HTTP connector input configuration

Output

The content of the response is stored in the token parameter by mapping it to the Content output parameter.

Output parameter Value
Content token

 

To extract the authorization token from the response and create the authorization header, add the following code to the process procedure of the authentication action:

set @header = '[{ "Key": "Authorization", "Value": "Bearer ' 
+ json_value(@token, '$.access_token') + '" }]'

 

HTTP connector: call web service

The next process action calls the required web service, which in this example is a service to list all groups.

 

Input

The input parameters of the process action should be configured like this:

Input parameter Assignment Value
URL Constant value https://graph.microsoft.com/v1.0/groups?$select=displayName
HTTP method Constant value GET
Headers Variable header

 

Output

The output parameter Content should be assigned to the response parameter.

Output parameter Value
Content response

After the call, the response parameter will have the following JSON content:

 {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups(displayName)",
"@odata.nextLink": "https://graph.microsoft.com/v1.0/groups?$select=displayName",
"value": [
{
"displayName": "Business Development"
},
{
"displayName": "Marketing"
},
{
"displayName": "Service & Care"
},
{
"displayName": "Product Innovation"
},
...
]
}

 

Process the results

To process the results, use the SQL Server json_value and openjson functions, for example:

select json_value(a.value, '$.displayName') as displayName from openjson(@json, '$.value') a

| displayName |
| -------------------- |
| Business Development |
| Marketing |
| Service & Care |
| Product Innovation |

8 replies

Userlevel 4
Badge +14

Hi @Jasper,

I asume, the new OAuth will help to make this kind of scenario’s much more flexibel and easier to implement.

Could you share some example’s of process flows which use the OAuth connector?

My ultimate goal is to allow end users to establish a link with their personal Off365 mailbox without the intervention of an administrator.

Userlevel 4
Badge +1

@Jasper @Vincent Doppenberg For the use case of sending Teams chat messages to users from our Azure AD Registered Thinkwise App we're trying to get the Graph API working, which requires us to use Delegated permissions instead of Application permissions. We have updated the permissions in the App Registration and also provided Admin consent for these permissions. However, I'm stuck at the 2. Get authorization step.

Insomnia returns me:

And trying the above URL in the browser causes the following error in Indicium:

8000042b-0001-ea00-b63f-84710c7967bb [ERR] Error logging in from external identity provider: Microsoft (17ebc8e3) 
System.Exception: Unable to unprotect the message.State.

Is this supposed to work with Indicium? If yes, what am I doing wrong?

Userlevel 5
Badge +2

EDIT: I was a bit too hasty with my reply

Userlevel 5
Badge +2

Hello Arie,

Just to clarify, do the messages need to be sent by the user that is logged in in Indicium (i.e. any user to any user) or would it suffice if the messages were sent by some type of bot account and only the recipient is important (i.e. bot user to any user)?

Also, what will be the trigger for a message to be sent? Will users do this from the Universal GUI, will it be an API call from a third party or will it be a scheduled system flow, for instance?

Userlevel 4
Badge +1

@Vincent Doppenberg Use case is as follows (for now):

  1. User creates Task for another User in Universal GUI
  2. Trigger creates a notification in our API queue table
  3. Scheduled System Flow pushes Notification to Teams chat of User to whom Task is assigned
  4. Idea is to send Notification with a generic O365 account (i.e. bot to user-like)

I’m open to alternative solutions that support the same use case through Graph API.

And in response to your edited comment, just as FYI: tested this on our DEV instance, which is setup as follows:

  • Elastic Beanstalk with Application Load Balancer, but a single EBS instance behind it so far
  • Instance runs both indicium_sf and indicium (for IAM - this one has OpenID config)
  • A localhost runs another indicium for IAM (without OpenID config): I’ll test later again after terminating this server → EDIT: it did have OpenID configured as well, nevertheless, stopping the local indicium instance did not have any impact. Still same error.
Userlevel 5
Badge +2

Hello Arie,

My edited was reply was slightly related and your error message might even disappear, but I don’t think it’s a step towards the solution.

To implement something like this, you’ll need the following prerequisites:

  • A refresh token for this generic O365 account. You can obtain this refresh token through Insomnia for instance. This will be a one time action to bootstrap the system flow, which from then on can produce it’s own refresh tokens and access token. To do this, you can follow the steps in the screenshot below, when prompted by Microsoft Graph to log in, log in with this generic O365 account.
  • Register an OpenID server configuration in the Software Factory for Microsoft Graph. You will need to enter the same URLs and client id/secret there as you did in Insomnia.
  • Do not configure the Microsoft Graph OpenID Server in Indicium’s appsettings, this isn’t necessary.
  • Do not configure the same OpenID client that you configured in Microsoft Graph in IAM as well, this isn’t necessary.

Once this is all done, you’ll want to design your system flow in a way like this:

  1. A Decision process action that reads the refresh token from the database and stores it in a process variable (you will need to store the initial refresh token that you got from Insomnia manually to bootstrap this). You may also want to fetch the necessary information for the chat message that you want to send here.
  2. An OAuth Refresh Token Connector process action. When creating this process action, select the OpenID Server configuration that you have made for Microsoft Graph. It accepts the refresh token as an input parameter and it will give you an access token and a new refresh token as output parameters, save both of them to process variables. Update the refresh token in the database with the new refresh token in the process procedure of this process action.
  3. An HTTP Connector that performs the chat API call on Microsoft Graph. You will need to provide a Bearer Authorization header with the access token in this request in order to send it as the generic O365 account. You can set the headers input parameter with the following constant value.
    [{ "Key": "Authorization", "Value": "Bearer {access_token}" }]

That should be it. This flow can be further optimized by only refreshing the access token when it is actually necessary, which might be once per hour or once per day for instance. To do this you can save the access token and its expiry date in the database as well and skip the 2nd process action based on this expiry date.

I hope this helps.

Userlevel 4
Badge +1

@Vincent Doppenberg Thanks a lot for the guidance and clarification. I managed to get a refresh token using Insomnia now: one step further!

  • Register an OpenID server configuration in the Software Factory for Microsoft Graph. You will need to enter the same URLs and client id/secret there as you did in Insomnia.

To be clear: I assume you mean we need to configure it here in the SF?

 

Userlevel 5
Badge +2

Hello Arie,

That’s great! Yes, you can configure an OAuth server there. Be sure to check “Request refresh token” and configure the Scopes as well, though I don’t think it matters for this specific use case.

Reply