Tag: MicrosoftGraph

An Outlook Add-in with SharePoint Framework (SPFx) – Store custom metadata with your mail

An Outlook Add-in with SharePoint Framework (SPFx) – Store custom metadata with your mail

Since SharePoint Framework version 1.10 you can also develop Office Add-Ins with SPFx starting with Outlook Web Access in public preview. The great benefit is you already have the prepared context for access of Microsoft Graph. In a demo scenario I showed you how to create a valuable Outlook Add-In with the capability to store complete mails to OneDrive, Office 365 Groups or Microsoft Teams.

Recently I presented that solution in the Microsoft SharePoint Framework bi-weekly community call.

During the call in the chat the idea was born to enhance this solution with some metadata. In fact to store with the mail so it is persisted by when this mail was saved where. Many thanks to Neelamugilan Gobalakrishnan and my colleague and MVP Wictor Wilen for your feedback on this.

Now I want to show you a simple solution for that. The existing project will only be enhanced by a simple operation to save an openExtension to the message. And when we open the Add-In we first try to get an existing openExtension for that mail and display as a reminder when and where we previously saved that mail in case that openExtension exists.

Now why an open extension you might think? Of course it depends if you use the (more simple) scenario of an open extension or the more complex but also more valuable schema extension scenario.

As per this great post from Mikael Svenson I have three arguments for the choice of open extensions:

  • I do not want to run a filter query on my messages based on the open extensions
  • I do not need my schema going public
  • I do not want that metadata schema being irreversible stored (you can only deprecate it for reasons once ‘Available’)

So lets start with the expected result. Once we open our existing add-in to store our mail somewhere we might want to have a hint like this that we already stored our mail previously and where:

Outlook add-in informs you about previous save operation

To achieve this we first need to store that information during our save process. In our controller we create another function that stores our metadata as an open extension to that mail. This works simply like that:

The function retrieves the id of the mail, a displayName, an url of the target location and finally a date. The displayName we construct from the target (OneDrive or Group/Team name) combined with the path we already displayed in our breadcrumb. That’s all for the metadata storage.

Now back to the start of our add-in where the requirement is to retrieve potentially existing metadata to remind the user in case the mail was already stored somewhere. In our base component we try to get the metadata once our graphController is established. As per the get an existing openExtension documentation you can either get the specific extension or expand the extension when getting a known instance, that is your mail. We will do the latter one as we do not know if the extension exists at all and in the former option a non existing extension would raise an error (which we could handle but that’s not the elegant way of course).

The graph request tries to retrieve the mail again only with id and subject but also with the expanded extension. In case there is metadata we return that as an object otherwise null. The result will be written to the components state and rendered in case it is not null.

Display in case metadata is filled
Display in case metadata is null

That’s all with my little enhancement using custom metadata for mails based on Microsoft Graph open extensions for my Outlook add-in.
You can check the full code repository here in my GitHub.

Markus is a SharePoint architect and technical consultant with focus on latest technology stack in Office 365 and SharePoint Online development. He loves the new SharePoint Framework as well as some backend stuff around Azure Automation or Azure Functions and also has a passion for Microsoft Graph.
He works for Avanade and is based in Munich.
Although if partially inspired by his daily work opinions are always personal.
An Outlook Add-in with SharePoint Framework (SPFx) – Retrieving the mail as Mime

An Outlook Add-in with SharePoint Framework (SPFx) – Retrieving the mail as Mime

Since SharePoint Framework version 1.10 you can also develop Office Add-Ins with SPFx starting with Outlook Web Access in public preview. The great benefit is you already have the prepared context for access of Microsoft Graph. In this demo scenario I want to show you how to create a valuable Outlook Add-In with the capability to store complete mails to OneDrive, Office 365 Groups or Microsoft Teams.

An Outlook Add-In to copy a whole mail to Teams, Groups or OneDrive

In this part you will see how to retrieve a mail as a whole mimestream so you can later store it as a file. In the past this was possible with the (meanwhile deprecated) Exchange asmx web-Services. Nowadays at there is also a Microsoft Graph endpoint for this.

The Api is simple me/messages/${mail.id}/$value
In the following function we are calling that endpoint and using the response to handover to next function for storing it somewhere.

GraphController: Retrieve Mail as MimeStream

Several parameters are not really needed here they are just handed in to handover to the next function for handling the response. The only needed parameter here is the mail respectively its id.

Once we have a positive result we need to check the size of the response, that is our mimestream. This is because for a file save operation via Microsoft Graph there are two different scenarios one simple scenario for files smaller than 4MB and a more complex one for files larger than 4MB. But this difference we will cover in the final part where we handle the storage operation of the the mimestream to a Group, Team, SharePoint or OneDrive. So stay tuned.

Meanwhile you can check the full code repository here in my GitHub.

Markus is a SharePoint architect and technical consultant with focus on latest technology stack in Office 365 and SharePoint Online development. He loves the new SharePoint Framework as well as some backend stuff around Azure Automation or Azure Functions and also has a passion for Microsoft Graph.
He works for Avanade and is based in Munich.
Although if partially inspired by his daily work opinions are always personal.
An Outlook Add-in with SharePoint Framework (SPFx) – Browsing your target OneDrive, Groups, Teams

An Outlook Add-in with SharePoint Framework (SPFx) – Browsing your target OneDrive, Groups, Teams

Since SharePoint Framework version 1.10 you can also develop Office Add-Ins with SPFx starting with Outlook Web Access in public preview. The great benefit is you already have the prepared context for access of Microsoft Graph. In this demo scenario I want to show you how to create a valuable Outlook Add-In with the capability to store complete mails to OneDrive, Office 365 Groups or Microsoft Teams.

An Outlook Add-In to copy a whole mail to Teams, Groups or OneDrive

In this part you will see how to retrieve all joined Groups or Teams and further retrieve the drives or folders, also from OneDrive, to browse them and select one as the target.

The UI simply follows quite the same process than moving an item within OneDrive or SharePoint. At first you can select your target system OneDrive, Office 365 Groups or Microsoft Teams.

Once you click one, and here we start with Groups respectively Teams as they are “higher” in terms of object hierarchy, we need to list all available Groups or Teams to the user . Therefore we have two functions in our GraphController.

GraphController: GetJoined Groups and Teams

As we do not need specific attributes of Groups and Teams, only as a parent container for browsing we treat them as a folder (IFolder interface). Drives and folders itself will only need the same attributes (id, name, optionally reference to parent item).

At the beginning of our “Groups” or “Teams” component we call that method and put the retrieved items as folders to our state.

We then render them in a simple way. This will be repeated later for all child items the same way.

Teams component (Groups component quite similar)
Folder component

Interesting is the subFolderCallback attribute of each folder which is set in the render function. In case we have a parent item (which has a parentFolder of null) we know this is a Group or Team. So once you click on it you want to see the drives below. In all other cases such as a drive or a folder a click on it wants to retrieve folders as child components. This is always the same method.

GraphController: GetDrives and SubFolders

As a folder has a parentFolder attribute of same type IFolder that parent also has/can have a parentFolder. With that information we can also create our simple breadcrumb.

Breadcrumb component

This breadcrumb can have up to three parts:

A << root anchor which brings you back to the root. The grandParenFolder (here “Folder 1”) which has a link and brings you one level up and a parentFolder (here “Subfolder 1”) which is not linked as it is the current location where you would store your mail right now in case you push the button and from which you might see eventually available child items.

In OneDrive it works quite the same but with two levels less as you only have one OneDrive (and not several Groups or Teams) and directly want to list the first level of folders once you open it. From there the functionality is quite the same.

In the next part we will get to know how to retrieve our mail as a full MimeStream object from Microsoft Graph.

Meanwhile you can check the full code repository here in my GitHub.

Markus is a SharePoint architect and technical consultant with focus on latest technology stack in Office 365 and SharePoint Online development. He loves the new SharePoint Framework as well as some backend stuff around Azure Automation or Azure Functions and also has a passion for Microsoft Graph.
He works for Avanade and is based in Munich.
Although if partially inspired by his daily work opinions are always personal.
An Outlook Add-in with SharePoint Framework (SPFx) – Introduction

An Outlook Add-in with SharePoint Framework (SPFx) – Introduction

Since SharePoint Framework version 1.10 you can also develop Office Add-Ins with SPFx starting with Outlook Web Access in public preview. The great benefit is you already have the prepared context for access of Microsoft Graph. In this demo scenario I want to show you how to create a valuable Outlook Add-In with the capability to store complete mails to OneDrive, Office 365 Groups or Microsoft Teams.

An Outlook Add-In to copy a whole mail to Teams, Groups or OneDrive

Let’s start the first part by creating our first Outlook Add-In. It’s already documented quite well in a Microsoft tutorial and I won’t repeat the necessary steps here and they are also quite familiar to you I suppose as you are not new to SharePoint Framework.

The only difference I made to the tutorial above and what you can do as well of course: Use the “React Framework” instead of “No JavaScript Framework”.

At first lets only take a short look into the Outlook Add-In manifest. I won’t go into details about changing position or logo or something but at least a custom title we should give. Therefore open the XML file in the \officeAddin folder and set the following settings according your choice:

What we need to do next is to get our current mail as we want to run our add in in the context of a selected mail. The following code snippet simply handles that:

Base Webpart render function

We first check this.context.sdks.office and if we have that we try to use this.context.sdks.office.context.mailbox.item. From there we can retrieve the mail ID and the subject which we will need at a later point of time. We hand them over to our first React component and in case we found nothing we will handle that null value adequately. On top we hand over the msGraphClientFactory which we will use to connect to Graph for folder retrieval, mail storage and so on.

That component I reduced a bit in code and explanation here. The main task is to render the initial logic for browsing your Teams, Groups or OneDrive folders but also hold the storage methods. Both I will cover in separate parts. The full code you can find in my GitHub repository.

Base Component

First we instantiate a GraphController and once ready it is set to the state so we know it’s there and can display our entry points for OneDrive, Groups and Teams accordingly.

In the second part we will get to know the browsing logic through all available Teams, Groups respectively OneDrive Folders where we can store our mail.

Meanwhile you can check the full code repository here in my GitHub.

Markus is a SharePoint architect and technical consultant with focus on latest technology stack in Office 365 and SharePoint Online development. He loves the new SharePoint Framework as well as some backend stuff around Azure Automation or Azure Functions and also has a passion for Microsoft Graph.
He works for Avanade and is based in Munich.
Although if partially inspired by his daily work opinions are always personal.
Provision Microsoft Teams with Azure Automation – Part II

Provision Microsoft Teams with Azure Automation – Part II

I am a big fan of Azure Automation and its helpful capabilities around provisioning and administrating around Office 365 and its components such as SharePoint, Office 365 Groups or Microsoft Teams. In this little series I want to show you how you can provision your Teams with Azure Automation in a quick and simple way but the same would be scalable to a much more complex solution depending on your needs.

In this second part of my little series I want to show you the way currently supported in production to first create a Group and then a Team based on that. Also we will have a look how we can further adjust that Team by execute some PnP Provisioning templates against it and its corresponding SharePoint site. Finally some adjustments to the Team (not possible with PnP Provisioning so far) will be done.

To remember what I started to explain in Part I. We have a modularized approach consisting of several runbooks where one needs to be called first.

  • Parent Runbook Module (calls:)
    • Create Team runbook
    • PnP Provision against site
    • Execute further PS manipulations …
All our Runbooks for creating Microsoft Teams (Part I & II of this series)

Our parent runbook you might remember from Part I but here once again and a bit more complete.

Our parent runbook to create a team from a group

After our input parameters we retrieve our assets (credentials, AppIDs, Urls and so on) from the current Automation Account (refer to another of my posts in case you need more information on Automation Account assets). Once we have them we can start to call our first runbook to create the Team (see next) which we already did in part I but there with another approach.

Our (sub)runbook to create an Office365 Group first and afterwards a team from it

Most code parts are the same as in part 1. We first connect to Microsoft Graph and get the access token. Then we create our Rest header. Also the block to receive the user id for the given login is the same. What’s new is the first While loop where we check if the desired alias is already in use. If so we manipulate it by attaching a “2”, next a “3” and so on. This pattern is only an example of course but gives us a bit more control in case we cannot handle something more comfortable in a potential UI.

As in this part we want to create a Group first it’s now time to create a GroupRequest body object. Additionally to an intro video on this approach by Paolo Pialorsi I already referenced in part 1. I also provide the alias here as we already managed that above and furthermore it is good practice to not provision Groups without any owners.

Next is to convert the request object to Json and execute a Rest call against Microsoft Graph. Having the Group and it’s ID as a result we can immediately go on with preparing the next request to create a Team from that Group (“teamify”). The request is a bit smaller than in part 1 but thats obvious because many parameters we already provided for the Group. The request follows the same pattern, converting request object to Json, execute Rest request and grabbing the ID from the result (which is not really necessary because Team and Group ID are in fact the same!)

After the new Team is created (back in our parent runbook!) we can retrieve a Group object and with it its site url. With a small waiting loop we check that the team and its site is really ready as provisioning might take some time. Having that we can call our further runbooks to go on provisioning with a PnP template and further PS cmdlets.

Next step is applying a PnP Provisioning template with that we want to create some fields, a content type and a list. The list will also get some DataRows so we have content for demonstration purposes. The runbook for that you find next:

Our (sub)runbook to apply PnP Provisioning template

First you find a function to download our existing provisioning template from an Azure Blob storage secured by a key.

PnP Provisioning template, stored in Azure Blob storage

Next we establish the authentication against SharePoint. You can either grab credentials from our AutomationAccount as a credential asset or use modern authentication with an app reg and certificate as described here.

After Connect-PnPOnline we construct our template-name, download it to local runbook runtime environment (C:\Users\… or C:\temp\… are our options) and then we simply apply our provisioning template.

Unfortunately I was still not able to output PnP Provsiioning debugging information in a runbook output so the following line of code is obsolete. Any hint would be greatly appreciated.

Set-PnPTraceLog	-On -Level Debug 

Next we come to our third runbook. Not everything can be solved with PnP Provisioning unfortunately (or not yet). So we decided in our scenarios to isolate further code steps in another runbook, typically called afterwards. In this scenario lets assume we want to create a new tab in our team and show the just created SharePoint list in a website tab. This is what the third (sub)runbook will do for us.

First we connect to Microsoft Graph again. Might not be necessary as we did in the first (sub)runbook but better than the connection got lost. As we need to add a new Tab to a Channel we first need to identify our Channel by retrieving the “General” one.

Afterwards we create a request url based on the IDs of our Team and the Channel we just identified. Build an object for a Website Tab, converting it to Json and executing a POST request against Microsoft Graph is all we need to do to achieve our result.

The custom ShrePoint list, provisioned with PnP Provisioning to a Teams’ SharePoint site
And the same list embedded in a Teams Website tab for instance

I hope this post illustrated a bit how you can create even more complex provisioning solutions with Azure Automation and PnP PowerShell. The same is applicable for SharePoint only or Office 365 Groups of course. In the create runbook you already saw here how to create Groups. Replace this by creating SharePoint sites is an obvious possibility.

Depending on some feedback next might be to point out a bit more the basics of Azure Automation or an architectural discussion when it might make more or less sense to use compared with/combined to alternatives such as Azure (Durable) Functions, Site Designs and so on. Looking forward to receive some questions on that.

Markus is a SharePoint architect and technical consultant with focus on latest technology stack in Office 365 and SharePoint Online development. He loves the new SharePoint Framework as well as some backend stuff around Azure Automation or Azure Functions and also has a passion for Microsoft Graph.
He works for Avanade and is based in Munich.
Although if partially inspired by his daily work opinions are always personal.
Provision Microsoft Teams with Azure Automation – Part I

Provision Microsoft Teams with Azure Automation – Part I

I am a big fan of Azure Automation and its helpful capabilities around provisioning and administrating around Office 365 and its components such as SharePoint, Office 365 Groups or Microsoft Teams. In this little series I want to show you how you can provision your Teams with Azure Automation in a quick and simple way but the same would be scalable to a much more complex solution depending on your needs.

Inspired by a video from Paolo Pialorsi I wanted to establish some base runbooks in Azure Automation for provisioning Microsoft Teams. In the past I did lots of them for Sharepoint Online and Office 365 Groups.

As always striving for the latest and greatest I wanted to omit the two-step approach that also Paolo is showing in his video: First create an Office 365 Group and then enhance this Group to a Team. And indeed there is at least a beta Api in Microsoft Graph for directly creating a Team, based on an existing template:
POST https://graph.microsoft.com/beta/teams

The pattern is quite simple and similar to any other POST request, you need to

  • Care for authentication by creating a token and providing it in your request header
  • Create a body to provide information for the object to be created
  • Execute a POST request by handing in the header and body

While the token creation is similar to others and shown in the video of Paolo as well lets have a detailed look at the request body:

{
  "template@odata.bind": "https://graph.microsoft.com/beta/teamsTemplates('standard')",
  "displayName": "My First Team",
  "description": "My First Team’s Description",
  "owners@odata.bind": [
    "https://graph.microsoft.com/beta/users/<UserGuid>"
  ]
}

The first thing I missed here was a “mailNickname” or alias. I checked and tried out but you cannot provide that this way, at least at the moment, you need to rely on what Microsoft creates from your requested displayName. While on Groups provisioning I clearly preferred to give the user a chance to enter own wishes.

The second thing I found out (and here I moved away from Microsoft’s example in the beta documentation, as that wasn’t working) that you need to provide a user Guid. Same in Groups by the way if you want to provide at least one owner from the start (what you should!). So a user Guid for sure is no good idea to request from a user directly so we need some additional lines of code but lets come to that right now:

At first we connect against Microsoft Graph. A simple way to do that is with PnP PowerShell of course. I assume you already registered an app for creating Groups as documented here and we already grabbed our id, secret, domain (see later in another runbook). After connecting we get our access token and put that in a header object.

Next we come to the problem with the user Guid. Here we assume our user request provides a login name. With a simple Graph request we get the corresponding user and it’s id which we store in a variable.

Next we can fill our requestBody from above. Not only with the user Guid but also with displayName, description and also our template. I won’t go into details here but there are several Microsoft templates available and you can even override properties of the available templates. One problem we have are the escape charaters ” which enclose the template name!

"template@odata.bind" = "https://graph.microsoft.com/beta/teamsTemplates('standard')"

As in the next step we convert the just created body object to Json this wouldn’t work if we wouldn’t pipe the Json creation to a regex method called Unescape from Microsoft’s standard regex class. I found this simple but effective tip in another blogpost.

ConvertTo-Json -InputObject $teamRequest | % { [System.Text.RegularExpressions.Regex]::Unescape($_) }

The final thing now should be to invoke a Rest request of type Post to the teams Url and providing our just created header and body. We do that and store the response in another variable.

We would expect now to have our most recent created team in a variable and could use it’s Id to request it and do further things with that. Unfortunately this is the next insufficiency in the beta version we currently use: It returns NOTHING.

So for reasons of completeness I added some “weak” lines of code to get the “latest” Team created with our requested displayName. For sure such a method wouldn’t be 100% reliable. But hopefully this gets fixed before this Api is supported for use in production.

Finally I would start to show my regular concept on provisioning with runbooks: I always use a modularized approach because I hate PS scripts with tons of code lines. So I always use one parent runbook to be called that calls further runbooks for significant steps in my provisioning process usch as:

  • Create my site/Group/Team (that runbook I showed above)
  • Provision my artefacts with PnP Provisioning
  • Post Provisioning stuff, modifications where I need additional code and what doesn’t work with PnP Templates
  • Have Shared or Helper runbooks to be called from different runbook modules …

So in our case here is a simple parent runbook that calls the just mentioned “Create” runbook, retrieves back the created Team’s Id and processes this further.

First we grab our assets such as Graph access credentials and store them in $global:variables so we have them available in all called (sub) runbooks as well in case we need to share variables …

That was it for now. Hopefully there will be some progress with this Api on Teams creation soon. I will observe it and potentially update this post by then.

In the next part I will show you the approach which is already available for productional use (v1.0 Graph Api) to first create a Group and then a Team out of it and further modify the just created Team. There you will see additional things to note when handling Provisioning with Azure Automation runbooks. So stay tuned.

Markus is a SharePoint architect and technical consultant with focus on latest technology stack in Office 365 and SharePoint Online development. He loves the new SharePoint Framework as well as some backend stuff around Azure Automation or Azure Functions and also has a passion for Microsoft Graph.
He works for Avanade and is based in Munich.
Although if partially inspired by his daily work opinions are always personal.
Secure Azure Functions Part 1 – Use Azure KeyVault Secrets when accessing Microsoft Graph

Secure Azure Functions Part 1 – Use Azure KeyVault Secrets when accessing Microsoft Graph

This is the first post of a little series on secure Azure Functions working with Office 365. This first one is about “simple” credential (user/password or ID/secret) access. Next we are going to use an additional certificate while accessing SharePoint Online.

When secure access to APIs is needed from Azure Functions the challenge is to securely store access credentials or secrets. To access Microsoft Graph for instance for the OAuth authentication you need a ClientID and a secret. The question is now where to store this. Is it a good idea to store this in your code or AppSettings? Most likely not!

In this post I want to show you a simple scenario to access Microsoft Graph from an Azure function and retrieving the ClientID and AppSecret from Azure KeyVault.

Accessing Microsoft Graph in this case is only an example for an API access where a secret is needed.

The architecture scenario

01SecurelyAccessMSGraphFromAzureFunction

Our architectural scenario is an Azure function that is securely called, for instance from a SharePoint Framework (SPFx) component via the new AADHttpClient. Nevertheless we will omit the UI part in this post and fully concentrate on the backend side:

So there we have our Azure function which will securely retrieve access credentials from Azure Key vault. Having that it will securely authenticate against our backend Api, that is Microsoft Graph in our example.

At first we will start creating the “credentials” for our backend Api. In our case this is an Azure Active Directory app registration.

App registration to access Microsoft Graph

There are two versions for Azure App registrations. V1 and V2. For a detailed overview on the differences refer to here. But as we want to access Microsoft Graph and this is possible with V2 we will now use that one. In a later scenario we will access SharePoint Online which was only possible till recent past with V1 and then we will have a look at that variant.

For accessing V2 we open the Url https://apps.dev.microsoft.com/ and register a new converged application. We will need to

  • Enter a name
  • Copy the application Id (we can do this later as well)
  • Create a new secret and copy it (Attention, we CAN’T do this later as well, we only can create a new one if we forget)
  • Add the platform Web-Api
  • As we want to access Office 365 Groups and its owners:

    Add Application permission Group.Read.All and Directory.Read.All

  • You can uncheck Live SDK support

To manage V2 app registrations from Azure Portal as well is currently under preview at the time of writing (end of 2018). To use it, simply log in to https://portal.azure.com/, go to "Azure Active Directory" and then "App registrations (preview)". The steps then are quite the same then mentioned above but slightly simpler. We will have a look at this in a later scenario as through this way it is now also possible to handle SharePoint Online Api permissions.

Once you have registered your app you need to consent it. Use the following Url template:

https://login.microsoftonline.com/{tenant}/adminconsent?client_id={AppId_seeAbove}&state=12345&redirect_uri=https://localhost/myapp/permissions

The tenant can be your GUID our the full name ( .onmicrosoft.com ).

The redirect_uri is obsolete as it might not be reached after everything went fine so ignore the 404 error afterwards.

In the new app registration preview this step can be done directly from the app registration by one click (make sure you are logged in as tenant admin that has adequate permissions to grant them to all users).

GrantGraphAPIPermissions
Grant Microsoft Graph Api permissions (app registration preview)

Establish Azure KeyVault

Creating an Azure KeyVault is also straightforward with some small but important steps to notice. First we switch to “Key vaults” in the Azure portal and create a new one:

CreateKeyVault01

A unique name is necessary as well as the subscription and the ressource group. The rest we can keep as is for now.

Next we will add our created AppID and Secret to the Key vault:

CreateKeyVaultAddSecret01

We do this twice. Once for the ID (debatable, you might also put this only to the AppSettings but …) and once for the Secret (not debatable 😉 )

CreateKeyVaultAddSecret02

Before leaving the key vault for a moment we might note down it’s Url which we need for access from our code later:

CreateKeyVaultUrl

That’s it for the moment. Once we are going to retrieve them from our Azure function we will come back to establish access to the key vault.

Configure the Azure Function App

For the Azure Function App we basically don’t need something special. For those of you new to the topic pay attention to create the Function App via “App Services”:

CreateFunctionApp01

Additionally (for instance when consuming your Azure function from SharePoint Framework (SPFx)) you might need tp

  • Configure CORS settings
  • Configure Authentication

Both is described here.

Managed Service Identity (MSI)

For sure the access to the recently established Azure key vault is not “anonymous” but also secured. The trick to not having to handle another credential/secret is the “Managed Service Identity”.

We can simply extend our Azure function app to register with Active Directory. In a next step we allow access for that AAD registration (think of an AD account for that app which auto-authenticates against the key vault later on) to our Azure key vault.

In your function app select “Platform settings” and there “Managed Service Identity”

CreateFunctionAppMSI01

Next you simply turn MSI on and save it

CreateFunctionAppMSI02

That’s it. After a short while you can switch back to your Azure key vault. There you choose “Access policies” and “+ Add new”.

Under “Principal” search for the recently created app function name. It can be easily detected by the special icon logo. For permissions select “Get” and “List” at least for “Secret Permissions” (for a later scenario I already added the same for key and certificate…)

CreateKeyVaultAddMSIPrincipal01

Example Code

Retrieve Key Vault Secret

The first thing we need are our app credentials (ID / secret) to access Microsoft Graph afterwards. The retrieval is quite simple as we need no explicit authentication. It is handled implicitly by MSI.

The async task will return the secret for a given name. First we build the Uri for it, constructed by our base Url we noted above when establishisng our key vault and now retrieving it from the ConfigurationManager. The Url is something like:

https://<Your-Key-Vault-Name>.vault.azure.net

Then with that Uri we finally retrieve the secretValue asynchronously and return it back.

Access Microsoft Graph

To access Micrsoft Graph we use the MSAL library which is represented by the NuGet package “Microsoft.Identity.Client”. This library is designed to handle Azure AD V2 endpoint access with AccessTokens. It is still a pre-release as time of writing (end of 2018) but it is declared “production ready”. You could also use the ADAL library for this scenario (you find an alternative example in the source code) and will use this in a later scenario for V1 access. Further explanation you can find here.

We extract our Graph stuff to a separate controller. At first we need some basic values which we can either hardcode or retrieve from ConfigurationManager.

But on top we need our registered values from above which we included both in Azure KeyVault. We will provide them within our constructor.

Next thing is to establish a GraphServiceClient. Therefore we retrieve an AccessToken via MSAL and on behalf of our client app registration values.

Finally we have our Task to retrieve the data. In our small example case we want to check if  a given user account is owner of a given Office365 Group ID.

The Azure Function – Putting it all together

The magic is already shown but now we simply put it alltogther inside our Azure function.

For our simple demo scenario we expect an Office 365 GroupID and a user login from query parameters.

Next we retrieve our application ID and our application secret from Azure Key vault by using our static KeyVaultAccess class.

Having those values we instantiate our GraphAccess class.

Once we have it we finally call the isValid method to evaluate if the given login is owner of the given group. The method retrieves the login and group id but before it needs a “GraphServiceClient”. I showed you two methods (ADAL and MSAL version) inside the GraphAccess class and here the MSAL version is called. That’s it.

Conclusion

You could now call this function from a SPFx solution for instance but might also say: Hey, why not directly call the Graph from SPFx?

You are right but this is an example that can be simply adapted to your own API call (that is, not MSGraph but also needs a ID/Secret or user/password access). Furthermore you might not provide a privileged access to your users by admit WebApiPermissions. Or you need Graph access in combination with other backend code for instance?

An even better scenario for this is elevating SharePoint permissions. Therefore I am going to write another post establishing access to SharePoint Online from Azure function by using Azure Key vault. Here we will need a certificate on top. So stay tuned.

Executing batch requests with Microsoft Graph and SharePoint Framework (SPFx)

In my recent blogpost I wrote about using batch requests with the SharePoint Rest Api within a SharePoint Framework (SPFx) solution. Today I want to construct a similar scenario which shows batch requesting using the new Microsoft Graph access class within SPFx.

Please note that this approach  is currently, when writing this post (Jul-2018), in final preview mode and therefore not supported in production scenarios as it might be subject to change. A GA is expected with the next SPFx version (1.6.0) end of this month.

Update: This is now targeting the GA version from SPFx 1.6.0 on.

Lets start with a simple scenario. Suppose we have a bunch of Group IDs

Within our component we will do several things now. First within the constructor (you might use a Graph call several times within your code, otherwise you can also do it in your function) we instantiate a MSGraphClient.

As this is an async call now, it is debatable to do this in the constructor or at a later stage in componentDidMount. In larger projects I usually exclude the whole data stuff to a separate controller class which I instantiate in the constructor.
In a getGroupsData function we then create our requests based on the IDs of our Groups from above (Please note that we also handover an index which we can later use to simply identify the repsonse if needed as the repsonses might be ordered differently than the requests originally were):
What happens afterwards is one simple call to the Graph Api handing over all requests in the body. If no error occurs and we recieve a Status of 200 per response (also one single request might fail, for instance when we have provided a wrong Id) we can push the response part to our array based on our custom UnifiedGroup interface.
When every response is handled, we set our state which lets our component re-render as usual.
Please pay attention that there is a hard limit of 20 (!!) requests per batch request. So in case you would have more than 20 Ids (or something similar, this is a constructed scenarion of course) you need to create several batch requests, similar to a paging approach.
Before we can test our stuff, we also need to request permissions in the package-solution.json
For debugging with the workbench this is sufficient (this now works with SPFx 1.5.0!), when deploying our solution we have to grant that permissions by an admin tenant-wide also as described here.
Update: 2 additional things to mention here are the general request for “Windows Azure Active Directory” | “User.Read” which is required to have for all requests. On top I recently came across an obviously general limitation of having the string values for resources and scopes not more than 255 characters in total. So pay attention on this as well when having to request a significant number of Graph resources for instance. But as you only have to approve once you might split up your request over several packages but must rely on their all existence inside a tenant then.
Once we run our simple solution it might (simply rendered) look like this:
result
Finally for your reference the whole component’s source: