Building a PDF Document Pack with Microsoft Teams Tab and Azure Function

In this blog post, I will show you how to create a Microsoft Teams tab app that can convert various types of documents into PDF format and then merge them into a single document pack. This app will use the Microsoft Graph API to perform the conversion and merging operations and will leverage the Teams Toolkit v5.0 to enable single sign-on (SSO) authentication. The app will also use an Azure function as its backend to handle the communication with the Graph API.

App architecture

DocumentPack app Architecture


  1. Set up and install Teams Toolkit for Visual Studio Code v5.0 How to install Teams Toolkit v5.0.

  2. Node.js, supported versions: 14, 16, 18

  3. An Microsoft 365 account for development

The following steps will guide you through the process of building this app:

Create a new Teams tab app project using the Teams Toolkit v5.0.

  1. Open Visual Studio Code and install the Teams Toolkit extension from the marketplace.
  2. Click on the Teams icon on the left sidebar and then click on “Create a new Teams app”.
  3. Choose “Tab” as the app type
  4. Choose React with Fluent UI option under App Features Using a Tab
  5. Select Typescript as programming language
  6. Select the folder that will contain your project’s root folder
  7. Enter the Application name as “DocumentPack”

Update the env.local file

Add the following two parameters in the .env.local file


Configure add.manifest.json

Update Microsoft Graph API permissions in aad.manifest.json file.

   "requiredResourceAccess": [
"resourceAppId": "Microsoft Graph",
"resourceAccess": [
"id": "User.Read",
"type": "Scope"
"id": "Files.ReadWrite.All",
"type": "Scope"

"id": "offline_access",
"type": "Scope"

"id": "openid",
"type": "Scope"

"id": "profile",
"type": "Scope"



Create an api folder

Create an API folder on the root of the project. We will create an Azure function within the api folder in the following steps.

Update teamsapp.local.yml file

Update the environment variables step to the following. Visit this link for more detail about Provision cloud resources.

# Generate runtime environment variables
- uses: file/createOrUpdateEnvironmentFile
target: ./.localConfigs
HTTPS: true
PORT: 53000

# Generate runtime environment variables for the backend
- uses: file/createOrUpdateEnvironmentFile
target: ./api/.localConfigs
ALLOWED_APP_IDS: 1fec8e78-bce4-4aaf-ab1b-5451cc387264;5e3ce6c0-2b1f-4285-8d4b-75ee78787346;0ec893e0-5785-4de6-99da-4ed124e5296c;4345a7b9-9a63-4910-a426-35363201d503;4765445b-32c6-49b0-83e6-1d93765276ca;d3590ed6-52b3-4102-aeff-aad2292ab01c;00000002-0000-0ff1-ce00-000000000000;bc59ab01-8403-45c6-8796-ac3ef710b3e3

Create an Azure Function project

The next step is to create an Azure Function. Azure Functions are small, event-driven code snippets that run in the cloud. They are a great way to interact with the Microsoft Graph API.

To create an Azure Function, follow these steps:

  1. Create HTTP triggered Azure function using Visual Studio within the api folder created in the previous steps
  2. Install the following nuget packages
dotnet add package Azure.Identity
dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.Azure.WebJobs.Extensions.TeamsFx
dotnet add package Microsoft.Graph
dotnet add package PDFsharp-MigraDoc-GDI
dotnet add package System.Text.Encoding.CodePages
  1. You need to copy the following parameters from the api/.localConfigs files and paste them into local.settings.json
Variables Description
M365_CLIENT_ID Your AAD App client id
M365_CLIENT_SECRET Your AAD App client secret
M365_AUTHORITY_HOST Authority host for your AAD
M365_TENANT_ID Tenant id for your AAD tenant
ALLOWED_APP_IDS List of client ids which are allowed to call the function app. Split by semicolon ‘;’

Add Authorization for HTTP trigger

Your Azure Function app is public to any client. With TeamsFx binding extension, your function can reject unauthorized clients. Visi this link for more detail Microsoft.Azure.WebJobs.Extensions.TeamsFx

TeamsFx function extension does the following work for Teams app developers:

  1. Do authorization for HTTP trigger:
  2. Http request must have an Authorization header with an access token, the client id of which should be in the list of ALLOWED_APP_IDS or equal to M365_CLIENT_ID setting.
  3. Refresh the user access token in the request header if it’s about to expire.
  4. Provide user access token in TeamsFxContext as Azure Functions input binding.

Configure TeamsFx within Azure Function input binding

Configure TeamsFx Binding

Azure function to create pdf document pack

Following are the activities that will be performed by the Azure function

  1. Retrieve the access token from the request using TeamFx bindings
  2. Creating a Microsoft graph client using OnBehalfOfCredential using Azure.Identity
  3. Getting current user OneDrive root folder Id
  4. Process for each uploaded file
    • Create a temp file in OneDrive
    • Convert to pdf
    • Remove the temp file
  5. Merge all pdf files into a single document pack and upload the document pack to OneDrive

Debug application

  1. First, select the Teams Toolkit icon on the left in the VS Code toolbar.

  2. In the Account section, sign in with your Microsoft 365 account if you haven’t already.

  3. Press F5 to start debugging which launches your app in Teams using a web browser. Select Debug (Edge) or Debug (Chrome).

  4. When Teams launches in the browser, select the Add button in the dialog to install your app to Teams.

  5. Consent the Graph API permissions via the consent prompt

  6. Navigate to the api folder and open the Azure function in Visual Studio. Start debugging the Azure function project parallelly as well.

Source code


You can find the complete source code from GitHub.

Author: Ejaz Hussain
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.