In my last post, Securing an Azure Function App with Azure AD - Works with SharePoint Framework! , I showed how you can secure a REST API deployed as an Azure Function App using Azure Active Directory (AzureAD). This comes in quite handy when you want to secure some custom server-side business logic that's called from a SharePoint Framework (SPFx) client-side solution.
The SFPx docs show how to use APIs with permissions to the Microsoft Graph... permissions like Users.Read or Calendars.Read. Other docs show how to connect to custom services using the ever-present user_impersonation permission that's on every AzureAD app.
But what if you want to create your own permissions for your own service?
This post will explain how to add custom permissions to the AzureAD application that is used to secure your Azure Function.
In my course, Mastering the SharePoint Framework, I deploy a custom service that allows users with the correct permissions request a list of and write to, a collection of NASA Apollo missions. Ideally, I'd like to give admins the ability to grant one or both permissions to their tenant: Missions.Read and Missions.Write. Then in my service, I'd check what permissions were included in the OAuth access token to see if the caller had permissions to do the operation they were trying to perform.
Overview: Leveraging Custom Permissions in Azure AD Applications
In order to implement and leverage custom permissions in AzureAD applications, there are three things you need to do. One of these is something you do all the time with AzureAD applications, but the other two are more nuanced.
The three things you need to do are:
- Add custom permissions to AzureAD application
- Grant caller the new permission(s)
- Incorporate the permission into the service's codebase
Let's look at each one of these...
(1) Adding Custom Permissions to AzureAD Applications
To add custom permissions to an AzureAD application, you have to modify the application's manifest. This involves hand-editing a JSON file in the Azure AD Admin Center.
Head over to the new Azure AD Admin Center, login & then select Azure Active Directory from the navigation.
In the navigation, under the Manage section, select App registrations. You may have to click a button to see a list of all your applications.
Select the AzureAD application that is tied to your Azure Function App... the one I showed you how to create in the last post.
From the app's page, select the Manifest link in the toolbar. This will open the Edit manifest blade. Within the block of JSON that represents the manifest, find the collection
You should find one permission, as shown in this snippet:
I'm going to add two new permissions, one for the Mission.Read and another for Mission.Write:
AzureAD Application Manifest with Custom Permissions
Note that both have unique IDs that I had to create. What are those other properties? Strangely enough, the best docs I've found on them were from the Microsoft Graph docs: oAuth2Permission resource type.
Make sure to save all your changes!
(2) Grant caller the new permission(s)
This is the easiest of the three steps because it is something you already have to do with calling AzureAD secured services from SPFx. The SPFx docs explain how to do this: MSFT: Connect to Azure AD-secured APIs in SharePoint Framework solutions.
As I explained in my post Consider Avoiding Declarative Permissions with Azure AD Services in SharePoint Framework Projects, I prefer using the Office 365 CLI to grant my permissions. So, to grant my SharePoint Online tenant access to my service with these permissions, I'd just execute the commands:
(3) Incorporate the permission into the service's codebase
Last step... use these new permissions in your custom REST API codebase! I'm partial to using Node.js & TypeScript for my server-side work, but you can use anything you like.
Let's get one thing out of the way - our REST API can assume that the call it's receiving has been validated with proper authentication by Azure AD by the time we get the call. Why? that's part of the validation that Azure AD + Azure Function App integration that Azure is doing for us.
All we need to do is implement the business logic. To do this, I need to decode that token. The NPM package jsonwebtoken is useful for this. In another post, Validating Azure AD Generated OAuth Tokens, I show how you can decode this properly, but for now, this works:
Notice in this case I'm checking the
scp array, which contains the scopes (aka: permissions) that are in the OAuth access token.
I'm also checking the
upn which is the ID of the user who initiated the call. Yes... you can tell who the actual user is who initiated the call from SPFx!
This gives me boolean flags I can then use to check in the actual logic and either perform the requested operation, or just throw a permission error:
Using this pattern & the support for Azure AD secured REST APIs in SharePoint Online with SPFx, you can easily implement custom services and secure your business logic and data with custom permissions and even lock them down to specific users!