January 17th, 2019

MVP Article – SharePoint Framework web part with Microsoft Graph and PnPjs: step by step guide

So you want to build a SharePoint Framework web part which uses Microsoft Graph API through PnPjs. Here is step by step guide on how to do that.

A few months ago I wrote a similar post, however, things were changed, some things were simplified a lot, that’s why this is a revisited guide. Also, I’ve addressed some additional steps here. The source code is available on the official SharePoint/sp-dev-fx-webparts GitHub repository.

Prerequisites

  • SPFx >= 1.6
  • PnPjs >= 1.2.4

1. Scaffold SPFx web part solution with React

This step is pretty self-explanatory, simply run yo @microsoft/sharepoint, select React, give your web part a name, do not change other defaults asked by yeoman.

2. Install PnPjs dependencies

Run

npm install @pnp/common @pnp/odata @pnp/logging @pnp/graph @microsoft/microsoft-graph-types --save

to install all required PnPjs dependencies and @microsoft/microsoft-graph-types which contains useful type definitions for MS Graph types. You can also use –save-exact flag to persist specific versions and prevent automatic update to the most recent ones.

3. Configure PnPjs instance

This step is required for all PnPjs related solutions. You should configure PnPjs to make it aware of your environment and \ or application. In the case of an SPFx solution, the configuration part is very simple and straightforward. Open your web part code file and import setup method:

import { setup as pnpSetup } from '@pnp/common';

Add onInit and configure spfxContext with an instance of web part’s context:

public onInit(): Promise<void> { 
  pnpSetup({
    spfxContext: this.context 
  }); 
  return Promise.resolve(); 
}

The code looks simple, however, a lot of things will happen at runtime later on.

If we open PnPjs source code, graphlibconfig.ts, we will see that under fetchClientFactory getter there is a check for spfxContext property:

public get fetchClientFactory(): () => HttpClientImpl {
  const graphPart = RuntimeConfig.get("graph");
  // use a configured factory firt
  if (graphPart !== undefined && graphPart !== null && graphPart.fetchClientFactory !== undefined) {
    return graphPart.fetchClientFactory;
  }

  // then try and use spfx context if available
  if (RuntimeConfig.spfxContext !== undefined) {
    return () => AdalClient.fromSPFxContext(RuntimeConfig.spfxContext);
  }

  throw Error("There is no Graph Client available, either set one using configuration or provide a valid SPFx Context using setup.");
}

If the property is initialized, then fetchClientFactory will be initialized with a method, which returns an instance of SPFxAdalClient class.

fetchClientFactory returns an instance of a class, which implements fetch method. Fetch method simply sends http request, however it also can adjust ongoing http request or modify http headers or add authorization. In turn, SPFxAdalClient’s fetch method adds OAuth bearer access token to ongoing http request to make it authenticated against MS Graph endpoint.

If we inspect getToken method (inside SPFxAdalClient class):

public getToken(resource: string): Promise<string> {
  return this.context.aadTokenProviderFactory.getTokenProvider().then(provider => {
    return provider.getToken(resource);
  });
}

we will see that it uses SPFx feature called AadTokenProvider (first introduced in SPFx 1.6). It turned out that PnPjs uses some SPFx features for access token generation. What does it mean for us? It means that we should configure web API permissions for our web part accordingly because that’s the part of SPFx Web API permissions infrastructure which is used by PnPjs.

4. Add permission requests to the web part

Open ./config/package-solution.json and add permission requests:

"webApiPermissionRequests": [ 
  { 
    "resource": "Microsoft Graph", 
    "scope": "Group.Read.All" 
  } 
]

In my sample, I’m going to use Groups API. In your web part, you should add as many permission requests as your app needs.

5. Package your app

Run

gulp bundle --ship
gulp package-solution --ship

to package your app.

6. Upload the app to your app catalog

Locate your package at ./sharepoint/solution/your-app.sppkg. Upload that package to the app catalog. Upon uploading you will see below screen:

The message seems complicated, but what it means is that you should approve all permission requests which we added earlier.

7. Approve app permission requests

There are different ways to approve your permission requests (SharePoint Admin UI, PowerShell, o365 cli). The most simple one is through the new UI of SharePoint central administration. You can navigate to your old SharePoint admin center and click “Try new” UI from there. Or you can simply open a page https://<org>-admin.sharepoint.com/_layouts/15/online/AdminHome.aspx#/webApiPermissionManagement (replace <org> with your real organization name)

Go ahead and select your APIs and click Approve. Please note, that if you use this feature at your tenant for the first time, you might experience some issues. Sometimes it simply happens. I did a post on issues I had. There is a post by Waldek Mastykarz as well on a different set of issues you might see. If you see errors try to look for a solution in mentioned posts.

Now we’re ready with configuration part and can finally program our web part code.

8. Write code!

In my sample, I use Groups API to get all Azure AD groups and display in a list. The code which gets the data is fairly simple:

graph.groups.get<Group[]>().then(groups => {
  this.setState({
    groups
  });
});

When ready, simply run gulp serve and open hosted workbench (it only works in hosted one) to see it in action.

Once again, you can find the source code for this sample from the official SharePoint/sp-dev-fx-webparts GitHub repository.

About the Author

Sergei Sergeev is a Microsoft Office Development MVP, currently working as an independent developer and consultant with a focus on SharePoint Online, Office 365 and Azure. He loves modern trends in development for SharePoint with JavaScript, TypeScript, and NodeJS. He enjoys learning something new (fortunately SharePoint is a great place to learn something new every day), sharing knowledge, creating useful and interesting tools and making it available to the community via open source contributions on GitHub.

Sergei speaks on SharePoint events and user groups, regularly posts to his blog https://spblog.net and tweets from @sergeev_srg.

What is the MVP article series?

We have opened up our SharePoint developer blog also for the Microsoft MVPs who would like to share their articles around SharePoint development topics also through this channel. All articles written by MVPs are clearly indicated by using the “MVP article” prefix in the title of the blog post. If you are an MVP and would like to get some additional exposure, please send your suggestions around the article to spdevblogcommunity@microsoft.com email address and we can start a discussion on the suggestion and possible publishing schedule.

You can absolutely also do cross-posting of the article through your own blog, but we would prefer the material which is submitted as a suggestion, to be fresh and new, rather than something which has been released months ago. We will use both SharePoint and OfficeDev social media channels to promote these articles, so it’s a nice way to get you additional exposure for the community around the work you do.


SharePoint Team, Microsoft – 17th of January 2019