Tag: Azure Function

Secure Azure Functions Part 2 – Handle certificates with Azure KeyVault when accessing SharePoint Online

Secure Azure Functions Part 2 – Handle certificates with Azure KeyVault when accessing SharePoint Online

This is the second post of my little series on secure Azure Functions working with Office 365. The first one was about “simple” credential (user/password or ID/secret) access. Now we need to use an additional certificate.

Recently I spent lots of time with modern SharePoint authentication used in either Azure Automation or Azure Functions. For most of the parts there is some documenation but not as a whole and step-by-step guide. This is what this blog post wants to accomplish. One of the best existing posts is this one from Jeremy Hancock.

The Architecture Scenario

As in part 1 we use an Azure Function to be securely called from a SPFx webpart with AADHttpClient for instance. We do not use the user authentication but an impersonation. That is, an own Azure AD App Registration with own permissions. This can be a necessary scenario when you need elevated privileges (as SPFx directly only can use user permissions when calling SharePoint).

Example scenarios can be around provisioning or post-provisioning site modifications (where you want to allow specific users to handle stuff that needs elevated privileges).

01securelyaccessspofromazurefunction

The Azure Function is once again MSI enabled so it can authenticate “itself” against the Key Vault (which gave access to the function, see part 1). With the Client ID of an registered app, which is given SharePoint Api permissions, the Azure Function will access SharePoint.

Create a self-signed certificate

For this step we can reuse the certificate / description from my last blogpost.

But in short again:

  • Create a self signed certificate with New-PnPAzureCertificate cmdlet
  • Keep the PS window open, we need the certificate’s KeyCredentials in a minute
$Password = "******"
$secPassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
$cert = New-PnPAzureCertificate -Out "AzureAutomationSPOAccess.pfx" - `
 -ValidYears 10 `
 -CertificatePassword $secPassword
 -CommonName "AzureAutomationSPOAccess" `
 -Country "DE" `
 -State "Bavaria"

$cert.KeyCredentials
{
    "customKeyIdentifier": "zUFQhchR6FJ0...",
    "keyId": "4d2fe8fc-0dbb-45a7-...",
    "type": "AsymmetricX509Cert",
    "usage": "Verify",
    "value":  "MIIDJDCCAgygAwIBAgIQV9qo..."
}

App registration and SharePoint Online Api

For this step we can reuse the certificate / description from my last blogpost.

In short again:

  • Go to your Azure Portal 
  • Switch to Azure Active Directory
  • Choose “App registrations (preview)” version (the standard works either, but…)
  • Register an App with a name of your choice
  • Provide adequate SharePoint Api permissions (Application permissions for an elevated scenario!)
  • Grant your permissions with an admin account 
  • Insert Key Credentials in app registration`s manifest settings
Register Azure AD App registration
Provide SharePoint Api permissions
Paste KeyCredentials from certificate to app registation manifest

Import certificate in Azure Key vault

This is also quite the same than loading the certificate to an Azure Automation account:

You have to import the .pfx file under “Certificates” to your Azure Key vault by entering a name and the given password (to make sure you are the one who “controls” the certificate)

Example Code

We need three parts for this:

  • Our key vault controller as we had it in part 1 as well
  • An authentication helper class for establishing our authentication / client context
  • The Azure Function itself using both parts mentioned beforehand

Retrieve certificate from Key vault

It might not seem obvious but this step is quite similar to that one in part 1. Although we imported a certificate above (and not a secret), we now need to retrieve the secret of exactly that certificate first. And this works quite the same than in part 1.

The ‘magic’ happens afterwards: While in part one we simply returned the retrieved secret value, we NOW use that value to create a X509Certificate2 from it and return that one for further usage.

Access SharePoint Online

To access SharePoint Online we use a simple CSOM / MSAL combination.

In our helper class this time (in part 1 of this series I retrieved it via the Azure Key vault but for an ID this is not 100% necessary) we retrieve our client ID from configuration manager (your local.settings.json for local debugging, respectively the “Application settings” of your Azure function).

Then we create our MSAL Authentication context quite similar to my last blog post. Next step is once again retrieving an access token but this time we provide a combination of our ID and a X509Certificate2.

Final thing is to create a CSOM client context and attach the access token to every request.

Using it in an Azure Function

To use that stuff is also no rocket science anymore. For simplicity reasons I minimized the SharePoint operation itself to a simple web.Title retrieval. Of course that part is much more code in other scenarios but here I wanted to put attention on Key vault access and SharePoint authentication only.

Only two lines are really important to mention here. At first we retrieve our certificate by using our KeyVaultAccess-controller from above in line 8. Next we retrieve our SharePoint ClientContext from our SPOAuthHelper in line 10.

Conclusion

Modern SharePoint authentication becomes more and more relevant. Furthermore there is a necessity for a secure but comfortable handling of secret artefacts such as credentials, app secrets or private keys. The combination of Azure Function, Azure Key vault and modern SharePoint authentication addresses this. 

 

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.