Monday 12 June 2017

Access Microsoft Graph from classic SharePoint pages (SPFx GraphHttpClient preview: Under the hood)

Recently, an update to the SharePoint Framework was released which introduced some cool new features including ApplicationCustomizers, FieldCustomizers and CommandSets. You can read more about the announcement here:  Announcing Availability of SharePoint Framework Extensions Developer Preview.

What was particularly interesting to me was the introduction of the GraphHttpClient class which makes it really easy to call the Microsoft Graph from within the SharePoint Framework. To make a call to the Graph, all you have to do is:


And all the plumbing and authentication required to successfully execute the call is handled by the GraphHttpClient class.

At the time of this writing (12th June 2017) the only permission scopes available to the GraphHttpClient are Group.ReadWrite.All and Reports.Read.All So if you call any Microsoft Graph endpoints which require permission scopes apart from these, you will get an "Insufficient privileges to complete the operation." error.

Also, the GraphHttpClient is in preview right now and not meant to be used in production.

So lets see what's going on behind the scenes here. How does the GraphHttpClient get the correct access token scoped to the current user?

Turns out it is really straightforward. If you observe the traffic sent/received, you will notice that to get the access token, the GraphHttpClient makes a request to a new endpoint: /_api/SP.OAuth.Token/Acquire

Update 10/07: According to the guidance released recently, Call Microsoft Graph using the SharePoint Framework GraphHttpClient this endpoint is subject to change and not meant for use in production. But the good news is that as mentioned in this twitter conversation https://twitter.com/simondizparc/status/879636058446680064, Microsoft is working on making the Graph accessible outside the SharePoint Framework. So we will just have to wait until then.

I will just keep my post here for informational purposes:

Since this endpoint is hosted in SPO itself, it knows who the current user is and returns the correct access token. Some additional details are required to call the endpoint such as the current request digest and the resource for which the access token is required i.e. http://graph.microsoft.com

So in theory, if we replicate the behaviour of the GraphHttpClient in a classic SharePoint page, we would be able to call the same endpoint and get the access token. And it works!

Here is my code which uses simple jQuery to get the access token for the Microsoft Graph and makes a call to a /v1.0/groups endpoint. Since it is just JavaScript code, it can be called from a Content Editor or a Script Editor webpart on a classic SharePoint page as well!

And here is the result:


This is very interesting and can open up new possibilities!

6 comments:

Buckfast said...

Great post. Boggles the mind that you can't just ask for a token at the moment to call Graph from SP pages. Only way around it (to avoid redirecting the user from a page) seems to be to hide an iframe that handles the ADAL auth loop and then use the token when it's done in the parent page to call graph.

Particularly annoying when MS are going to drop GQL support in search at the end of the month. So the only way to now get information like trending docs is via MSGraph so you need a Graph token.

Look forward to them make graph more accessible.

Unknown said...

Hi,

Very interesting post. Can we call all graph end points like /users or /me also?

Unknown said...

hi

can you help me with the same to get list of tasks from outlook in SPFX.

Pratima Deshpande said...

Hi

I have tried above code in my SharePoint Online page. But it has responded with following error:

The user is required to use multi-factor authentication

It seems my page is already acquiring the access token. Any help is appreciated.

Thanks
Pratima Deshpande

Pratima Deshpande said...

Hi

Thanks for this post. I used the same code outside document.ready so it threw few errors. I wrote the code in ready then it ran successfully.

Milan said...

Yes, of course. You can call all graph api endpoints.