Deploy a single sign-on (SSO) Office Add-in to Microsoft Azure App Service
Office Add-ins that use SSO require server-side code. To support server-side code in deployment you need to use Azure App Service. Follow the steps in this article to deploy your Office Add-in to Azure App Service for staging or deployment.
Prerequisites
The steps in this article work for an Office Add-in created by the Yeoman Generator for Office Add-ins using the Office Add-in Task Pane project supporting single sign-on (localhost)
project type. Be sure you have configured the add-in project so that it runs on localhost successfully. For more information, see the Single sign-on (SSO) quick start.
Note
For information about deploying an Office Add-in that you created using Teams Toolkit, see Deploy Teams app to the cloud and Deploy your first Teams app. Add-ins created with the Teams Toolkit use the unified manifest for Microsoft 365. For more information about publication of add-ins and sideloading, see Deploy and publish Office Add-ins.
The steps in this article also require:
- An Azure account. Get a trial subscription at Microsoft Azure.
- Azure Account extension for VS Code.
- Azure App Service extension for VS Code.
Create the App Service app
The following steps set up a basic deployment of the Office Add-in. There are multiple ways to configure deployment that aren't covered in this documentation. For additional options on how to configure your deployment, see Deployment Best Practices.
Sign in to Azure
Open your Office Add-in project in VS Code.
Select the Azure logo in the Activity Bar. If the Activity Bar is hidden, open it by selecting View > Appearance > Activity Bar.
In the App Service explorer, select Sign in to Azure... and follow the instructions.
Configure the App Service app
App Service supports various versions of Node.js on both Linux and Windows. Select the tab for the one you'd like to use and then follow the instructions to create your App Service app.
- Right-click (or select and hold) on App Services and select Create new Web App. A Linux container is used by default.
- Type a globally unique name for your web app and press Enter. The name must be unique across all of Azure and use only alphanumeric characters ('A-Z', 'a-z', and '0-9') and hyphens ('-').
- In Select a runtime stack, select the Node 16 LTS runtime stack.
- In Select a pricing tier, select Free (F1) and wait for the resources to be provisioned in Azure. When prompted to deploy, don't deploy the add-in yet. You'll do that in a later step.
- Right-click (or select and hold) your App Service app and select Open in Portal.
- When the portal opens in the browser, copy the domain name of the URL (not the
https://
part) from the Overview pane and save it. You'll need it in later steps.
Update package.json
Open the package.json file. Then replace the
start
command in the"scripts"
section with the following entry."start": "node middletier.js",
Find the
"prestart"
entry in the '"scripts"' section and delete it. This section is not needed for this deployment.Save the file.
Update webpack.config.js
Open the webpack.config.js file.
Set the
urlDev
andurlProd
constants to the following values. (Note that thehttps
protocol is not specified.) This will cause webpack to replacelocalhost:3000
with your web site domain name in the/dist/manifest.xml
file.const urlDev = "localhost:3000"; const urlProd = "<your-web-site-domain-name>";
Find the first
CopyWebpackPlugin
section and update it to also copy the package.json file to the dist folder as shown in the following example.new CopyWebpackPlugin({ patterns: [ { from: "assets/*", to: "assets/[name][ext][query]", }, { from: "package.json", to: "package.json", }, { from: "manifest*.xml", to: "[name]" + "[ext]", transform(content) { if (dev) { return content; } else { return content.toString().replace(new RegExp(urlDev, "g"), urlProd); } }, }, ], }),
Save the file.
Update manifest
Open the manifest.xml file.
Replace
<SupportUrl DefaultValue="https://www.contoso.com/help"/>
with the URL of your web site help page.Replace
<AppDomain>https://www.contoso.com</AppDomain>
with the URL of your web site.In the
<Scopes>
section near the bottom of the file, add theopenid
scope as shown in the following XML.<Scopes> <Scope>User.Read</Scope> <Scope>profile</Scope> <Scope>openid</Scope> </Scopes>
Save the file.
Update fallbackauthdialog.js (or fallbackauthdialog.ts)
- Open the src/helpers/fallbackauthdialog.js file, or src/helpers/fallbackauthdialog.ts if your project uses TypeScript.
- Find the
redirectUri
on line 24 and change the value to use your App Service app URL you saved previously. For example,redirectUri: "https://contoso-sso.azurewebsites.net/fallbackauthdialog.html",
- Save the file.
Update .ENV
The .ENV file contains a client secret. For the purposes of learning in this article you can deploy the .ENV file to Azure. However for a production deployment, you should move the secret and any other confidential data into Azure Key Vault.
- Open the .ENV file.
- Set the
NODE_ENV
variable to the valueproduction
. - Save the file.
Update app.js (or app.ts)
The app.js (or app.ts) requires several minor changes to run correctly in a deployment. It's easiest to just replace the file with an updated version for deployment.
Open the src/middle-tier/app.js file, or src/middle-tier/app.ts if your project uses TypeScript.
Replace the entire file contents with the following code.
/* * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See full license in root of repo. --> * * This file is the main Node.js server file that defines the express middleware. */ require("dotenv").config(); import * as createError from "http-errors"; import * as path from "path"; import * as cookieParser from "cookie-parser"; import * as logger from "morgan"; import express from "express"; import { getUserData } from "./msgraph-helper"; import { validateJwt } from "./ssoauth-helper"; /* global console, process, require, __dirname */ const app = express(); const port = process.env.PORT; app.set("port", port); // view engine setup app.set("views", path.join(__dirname, "views")); app.set("view engine", "pug"); app.use(logger("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); /* Turn off caching when developing */ if (process.env.NODE_ENV !== "production") { app.use(express.static(path.join(process.cwd(), "dist"), { etag: false })); app.use(function (req, res, next) { res.header("Cache-Control", "private, no-cache, no-store, must-revalidate"); res.header("Expires", "-1"); res.header("Pragma", "no-cache"); next(); }); } else { // In production mode, let static files be cached. app.use(express.static(path.join(process.cwd()))); console.log("static set up: " + path.join(process.cwd())); } const indexRouter = express.Router(); indexRouter.get("/", function (req, res) { res.sendFile("/taskpane.html", { root: __dirname }); }); // Route APIs indexRouter.get("/getuserdata", validateJwt, getUserData); app.use("/", indexRouter); // Catch 404 and forward to error handler app.use(function (req, res, next) { console.log("error 404"); next(createError(404)); }); // error handler app.use(function (err, req, temp, res) { // set locals, only providing error in development console.log("error 500"); res.locals.message = err.message; res.locals.error = req.app.get("env") === "development" ? err : {}; // render the error page res.status(err.status || 500).send({ message: err.message, }); }); app.listen(process.env.PORT, () => console.log("Server listening on port: " + process.env.PORT));
Save the file.
Update app registration
We recommend you create multiple app registrations for localhost, staging, and deployment testing. The following steps ensure that the app registration you use for deployment correctly uses the App Service app URL.
In the Azure portal, open your app registration. Note that the app registration may be in a different account than your App Service app. Be sure to sign in to the correct account.
In the left sidebar, select Authentication.
On the Authentication pane, find the
https://localhost:3000/fallbackauthdialog.html
and change it to use the App Service app URL you saved previously. For example,https://contoso.sso.azurewebsites.net/fallbackauthdialog.html
.Save the change.
In the left sidebar, select Expose an API.
Edit the Application ID URI field and replace
localhost:3000
with the domain from the App Service app URL you saved previously.Save the changes.
Build and deploy
Once the files and app registration are updated, you can deploy the add-in.
- In VS Code open the terminal and run the command
npm run build
. This will build a folder nameddist
that you can deploy. - In the VS Code Explorer browse to the
dist
folder. Right-click (or select and hold) thedist
folder and select Deploy to Web App.... - When prompted to select a resource, select the App Service app you created previously.
- When prompted if you are sure, select Deploy.
- When prompted to always deploy the workspace, choose Yes.
If you make additional code changes, you'll need to run npm run build
again and redeploy the project.
Deploy updates
You'll deploy updates to your web application in the same manner as described previously. Changes to the manifest require redistributing your manifest to users. The process to do so depends on your publishing method. For more information on updating your add-in, see Maintain your Office Add-in.
Test the deployment
Sideload the ./dist/manifest.xml file and test the functionality of the add-in in Office. For more information, see Sideload an Office Add-in for testing.
Note
If your app registration is on a different tenant than where you sideload the add-in, the add-in will not have admin consent for Microsoft Graph. To test in this scenario you need an admin to centrally deploy the add-in on the Microsoft 365 tenant. For more information, see Deploy add-ins in the Microsoft 365 admin center
If you encounter any deployment issues, see the Azure App Service troubleshooting documentation. If you use central deployment, or plan to deploy to AppSource, we recommend you validate the Office Add-in's manifest using the '-p' option for production.
Next steps
Office Add-ins