HOMETOOLSAZURE GATEWAY PROVISIONER — KB
azure-provisioner.html · POC v1.0
KNOWLEDGE BASE // TOOLS // AZURE GATEWAY PROVISIONER
Azure Gateway Provisioner
Complete reference for using and deploying the Azure API Gateway Provisioner. Covers the 5-step wizard, all 7 ARM deployment operations, Key Vault secret management, Function App configuration, and the post-provisioning Auvik console update in a single document.
TOOLS AZURE KEY VAULT FUNCTION APP AUVIK API PROXY
FILE
azure-provisioner.html
AUTH
MSAL.js v2 — User Delegated
ARM SCOPE
management.azure.com/user_impersonation
RUNTIME
Node.js 18 · Functions v4
VERSION
POC v1.0
01
WHAT THIS TOOL DOES

The Azure Gateway Provisioner is a browser-based wizard that creates a complete Azure API proxy infrastructure for the Auvik network monitoring platform — without requiring the Azure CLI, PowerShell, Bicep, or Terraform. An engineer opens the HTML file, signs in with their Microsoft account, fills out a configuration form, and clicks Provision. The tool then calls the Azure Resource Manager API directly from the browser to deploy seven Azure resources in sequence.

The end result is a secure Azure Function App that sits between your MSP dashboards and the Auvik API. Auvik credentials never appear in browser code after provisioning — they are stored encrypted in Azure Key Vault and injected server-side on every request.

THE CORE PROBLEM IT SOLVES Any HTML page that calls the Auvik API directly must include Auvik credentials in client-side code — visible to anyone who opens DevTools. This provisioner creates a proxy server in Azure that holds the credentials securely. Dashboards call the proxy instead; the proxy calls Auvik. The browser never sees the credentials again.
1
APP REG
2
SIGN IN
3
CONFIGURE
4
PROVISION
LIVE
02
ARCHITECTURE

The provisioner creates a three-layer security architecture. The browser never touches the Auvik API directly after provisioning. Every request flows through the Function App, which reads credentials from Key Vault at runtime using its Managed Identity.

LAYERCOMPONENTROLECREDENTIAL EXPOSURE
ClientBrowser / Dashboard HTMLCalls Function App proxy endpointNone — no credentials in client code
ProxyAzure Function AppReceives requests, injects Auvik auth header, forwards to Auvik APICredentials read from Key Vault — never in code
SecretsAzure Key VaultStores Auvik username and API key encrypted at restOnly accessible to Function App Managed Identity
BackendAuvik APIActual network data source
AZURE RESOURCES CREATED
Resource Group
Container for all resources. Default name: rg-cyberadvisers-proxy. All resources below are created inside this group, making teardown a single delete operation.
Storage Account
Required backing storage for the Function App. Standard LRS, StorageV2. Default name: stcyberadvisers. Stores Function App files and the AzureWebJobs runtime state.
Key Vault
Encrypted secret store. Default name: kv-cyberadvisers. Holds two secrets: auvik-api-user and auvik-api-key. Configured with standard SKU and access policies for both the provisioning user and the Function App identity.
Consumption Plan
Serverless hosting plan (Y1/Dynamic). Zero cost when not in use. Named {funcapp-name}-plan. Scales automatically with request volume.
Function App
The proxy server itself. Node.js 18, Functions runtime v4. System-assigned Managed Identity enabled. Default URL: {funcapp-name}.azurewebsites.net. App settings include KV references so credentials are never stored as plaintext.
03
HOW IT WORKS
AUTHENTICATION MODEL

The provisioner uses MSAL.js v2 (Microsoft Authentication Library) running entirely in the browser. When you click Sign In, a Microsoft popup opens — your credentials go directly to Microsoft's login servers, never through this page. On success, MSAL returns an access token scoped to management.azure.com/user_impersonation, which the provisioner uses to make ARM API calls on your behalf.

For Key Vault secret storage (Step 5), the provisioner acquires a separate token scoped to vault.azure.net/user_impersonation and calls the Key Vault Data Plane API directly. Tokens are acquired silently when possible and via popup when a fresh login is required.

KEY VAULT REFERENCE PATTERN

The most important security mechanism is how the Function App reads credentials. Rather than storing the actual Auvik username and key in app settings (where they appear as plaintext in the Azure Portal), the provisioner stores Key Vault references — special strings that tell Azure to retrieve the secret from Key Vault at runtime.

APP SETTING VALUE IN THE FUNCTION APP (NOT THE ACTUAL SECRET)
AUVIK_API_USER = @Microsoft.KeyVault(VaultName=kv-cyberadvisers;SecretName=auvik-api-user) AUVIK_API_KEY = @Microsoft.KeyVault(VaultName=kv-cyberadvisers;SecretName=auvik-api-key)

Azure resolves these references automatically using the Function App's Managed Identity. The actual secret values never appear in the portal, in logs, or in any ARM API response.

CORS PROTECTION

The ALLOWED_ORIGIN app setting on the Function App controls which origins can call the proxy. During initial provisioning you can leave this blank (*) for testing. Before going to production, update this to your SharePoint tenant URL. This ensures only your dashboards can use the proxy — external sites cannot make calls to it even if they discover the URL.

04
STEP 1 — APP REGISTRATION

Before the provisioner can sign in with your Microsoft account, Azure needs to know this application exists. You register it once in Entra ID (Azure AD) and paste the resulting IDs into the form. This step takes about 3 minutes in the Azure Portal.

WHY THIS IS REQUIRED MSAL.js authenticates users through the OAuth 2.0 Authorization Code flow. Azure requires every application using this flow to be pre-registered so it can validate that the redirect URI is legitimate. Without an app registration, the login popup has nothing to return a token to.
Tenant ID
Your Azure Directory (tenant) ID. Found in Azure Portal → App registrations → your app → Overview → Directory (tenant) ID. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Client ID
Also called Application (client) ID. Found on the same Overview page as the Tenant ID. Uniquely identifies the app registration you created for the provisioner.
Redirect URI
Must be set to the URL where the HTML file is hosted. The provisioner auto-detects and displays the correct value at the bottom of Step 1. Copy it exactly — a mismatch causes login to fail with a redirect_uri_mismatch error.

After entering valid GUIDs for both fields and clicking Save & Continue, the provisioner initializes the MSAL instance and advances to Step 2. The step indicator turns green and shows a checkmark.

APP REGISTRATION NAME Name it cyberadvisers-provisioner (or similar). The name is only for your reference in the Azure Portal — it has no effect on functionality.
05
STEP 2 — SIGN IN TO AZURE

Click Sign In with Microsoft. A Microsoft login popup opens. Sign in with a work account that has at least Contributor rights on the Azure subscription you want to provision into. Contributor is the minimum required role — Owner is needed only if you also need to assign RBAC roles, which this provisioner does not do.

On successful login the page shows your account name, email, initials badge, and a subscription dropdown populated from your Azure account. Select the target subscription and click Configure Resources to advance to Step 3.

Account displayed
Your Microsoft work account name and email. Click "disconnect" to sign out and sign in with a different account. Tokens are stored in sessionStorage — they are cleared when you close the browser tab.
Subscription dropdown
Populated by calling the ARM Subscriptions API with your token. Only Active subscriptions are shown. If the dropdown is empty, your account either has no subscriptions or the token did not include the ARM scope — check that the app registration has the Azure Service Management user_impersonation permission with admin consent granted.
REQUIRED AZURE ROLE The signed-in account must have Contributor (or Owner) on the target subscription. Reader is not sufficient — the provisioner creates resources. If you see 403 errors during provisioning, check the account's role assignment in Azure Portal → Subscriptions → Access control (IAM).
06
STEP 3 — CONFIGURE RESOURCES

Step 3 is the configuration form. All fields have defaults pre-filled. Review each value before clicking Provision Gateway Server.

AZURE RESOURCE FIELDS
FIELDDEFAULTCONSTRAINTS
Resource Grouprg-cyberadvisers-proxyAny valid Azure resource group name. Does not need to be globally unique.
LocationeastusChoose the region closest to your team. All seven resources deploy to this region.
Storage AccountstcyberadvisersGlobally unique. Lowercase letters and numbers only. No hyphens. 3–24 characters. Will fail with a conflict error if the name is already taken.
Function App Namecyberadvisers-proxyGlobally unique. Becomes {name}.azurewebsites.net. Must be available — check at portal.azure.com if unsure.
Key Vault Namekv-cyberadvisersGlobally unique. 3–24 characters. Letters, numbers, hyphens only.
AUVIK API CREDENTIALS
Auvik API Username
Your Auvik login email address. This becomes the auvik-api-user secret in Key Vault. Used for Basic authentication on every proxied request.
Auvik API Key
Your Auvik API key. Found in Auvik: Account Settings → API Credentials → Generate API Key. This becomes the auvik-api-key secret in Key Vault. The field is masked (type="password") and the value is sent directly to Key Vault over HTTPS — it never appears in the terminal output.
Auvik Base URL
The regional Auvik API endpoint. Default: https://auvikapi.us1.my.auvik.com/v1. Swap us1 for your region: us1, us2, eu, or au. Check your Auvik account region in Account Settings.
SharePoint / Allowed Origin
The origin that will call the proxy. Example: https://yourtenant.sharepoint.com. Leave blank during testing (allows all origins via *). Must be locked down before production — this is the CORS restriction that prevents external sites from using your proxy.
CREDENTIALS HANDLING Auvik credentials entered in this form are transmitted directly to Azure Key Vault over HTTPS during Step 4. They are never logged to the terminal, never sent to any server other than Azure, and never stored by the HTML page itself. The API key field is masked at all times.
07
STEP 4 — PROVISIONING

Clicking Provision Gateway Server advances to Step 4 and begins the automated deployment. A real-time terminal output window shows every ARM API call, its result, and the generated resource URLs. A progress bar tracks overall completion across seven operations.

Total provisioning time is typically 3–8 minutes depending on Azure region latency and resource creation queues. The Function App creation step (Step 4/7) takes the longest — Azure provisions the consumption plan and registers the runtime before returning.

1/7
📁
Create Resource Group
ARM PUT · resourcegroups · Progress: 5% → 14%
14%
2/7
💾
Create Storage Account + Retrieve Connection String
ARM PUT · storageAccounts · POST listKeys · Standard LRS · Progress: 16% → 28%
28%
3/7
🔐
Create Key Vault
ARM PUT · vaults · Standard SKU · Access policies empty at creation · Progress: 30% → 42%
42%
4/7
Create Consumption Plan + Function App
ARM PUT · serverfarms (Y1/Dynamic) · ARM PUT · sites · System-assigned Managed Identity enabled · Progress: 44% → 60%
60%
5/7
🔑
Store Auvik Credentials in Key Vault
Grant current user KV access · Acquire KV token · PUT secrets/auvik-api-user + secrets/auvik-api-key · Progress: 62% → 74%
74%
6/7
🔗
Grant Function App Key Vault Access + Update App Settings
POST accessPolicies/add for principalId · PUT appsettings with KV reference strings · Progress: 76% → 88%
88%
7/7
Finalize — Output URLs
Generate proxy URL and health URL · Log to terminal · Advance to Step 5 · Progress: 95% → 100%
100%
IF PROVISIONING FAILS The terminal displays the exact ARM error (HTTP status + error body) for the failing step. Click "← Back to Config" to return to Step 3, correct the issue (usually a name conflict or permission error), and then click Provision again. Resources created in earlier steps are not rolled back automatically — if you need a clean slate, delete the resource group in the Azure Portal before retrying.
TOKEN EXPIRY DURING LONG RUNS ARM access tokens expire after 1 hour. The provisioner calls acquireToken() before each ARM operation and refreshes silently via MSAL. If the session has expired a login popup re-appears mid-run. Complete the login and the provisioning continues from where it left off on the next operation.
08
STEP 5 — GATEWAY LIVE

Step 5 confirms all resources were created successfully and shows six result cards with all generated URLs and resource names. Each value has a copy button. This is the screen to screenshot for your deployment record.

PROXY ENDPOINT
https://{funcapp}.azurewebsites.net/api/auvik
HEALTH CHECK
https://{funcapp}.azurewebsites.net/api/health
FUNCTION APP
{funcapp}.azurewebsites.net
KEY VAULT
{keyvault}.vault.azure.net
RESOURCE GROUP
{rg} in {location}
SUBSCRIPTION
{subscription-id}

The page also shows a before/after code snippet for updating any Auvik console dashboards to use the proxy URL instead of the direct Auvik endpoint. See Section C5 for the full update process.

The Run Health Check button calls the /api/health endpoint and shows the raw JSON response. Note that this will return a 404 or connection error until the Function App code is deployed separately — the provisioner creates the Azure infrastructure but does not deploy the Node.js function code. See Section C4.

09
ARM DEPLOYMENT STEPS REFERENCE
#RESOURCEARM METHODAPI VERSIONWAIT FOR COMPLETE
1Resource GroupPUT /subscriptions/{sub}/resourcegroups/{rg}2022-12-01No
2aStorage AccountPUT .../storageAccounts/{name}2023-01-01Yes
2bStorage KeysPOST .../storageAccounts/{name}/listKeys2023-01-01
3Key VaultPUT .../vaults/{name}2023-07-01Yes
4aConsumption PlanPUT .../serverfarms/{plan}2023-12-01Yes
4bFunction AppPUT .../sites/{funcapp}2023-12-01Yes
5aKV Access Policy (user)POST .../vaults/{kv}/accessPolicies/add2023-07-01No
5bKV Secret — userPUT https://{kv}.vault.azure.net/secrets/auvik-api-user7.4 (data plane)
5cKV Secret — keyPUT https://{kv}.vault.azure.net/secrets/auvik-api-key7.4 (data plane)
6aKV Access Policy (func)POST .../vaults/{kv}/accessPolicies/add2023-07-01No
6bApp Settings UpdatePUT .../sites/{func}/config/appsettings2023-12-01No
10
FUNCTION APP SETTINGS

These are the app settings written to the Function App by the provisioner. Settings marked as KV Reference never contain the actual secret value — Azure resolves them at runtime using the Function App's Managed Identity.

SETTING NAMEVALUE / PATTERNPURPOSE
FUNCTIONS_WORKER_RUNTIMEnodeTells the runtime to use Node.js
FUNCTIONS_EXTENSION_VERSION~4Functions runtime version 4.x
WEBSITE_NODE_DEFAULT_VERSION~18Node.js 18 LTS
AzureWebJobsStorageDefaultEndpointsProtocol=https;AccountName=...Storage connection string for runtime state
WEBSITE_CONTENTAZUREFILECONNECTIONSTRINGSame as AzureWebJobsStorageFile share for Function App code
WEBSITE_CONTENTSHARE{funcapp-name}File share name
AUVIK_API_USER@Microsoft.KeyVault(VaultName=...;SecretName=auvik-api-user)KV reference — actual value resolved by Managed Identity
AUVIK_API_KEY@Microsoft.KeyVault(VaultName=...;SecretName=auvik-api-key)KV reference — actual value resolved by Managed Identity
AUVIK_BASE_URLhttps://auvikapi.us1.my.auvik.com/v1Auvik regional API base URL
ALLOWED_ORIGINhttps://yourtenant.sharepoint.com (or *)CORS allowed origin for proxy responses
REQUIRE_AUTHfalseWhether incoming requests to the proxy require auth. Set to true and add auth logic in function code for production.
11
KEY VAULT SECRETS
SECRET NAMEVALUESTORED BYREAD BY
auvik-api-userAuvik account email addressProvisioner (Step 5) using provisioning user's KV tokenFunction App via Managed Identity at request time
auvik-api-keyAuvik API keyProvisioner (Step 5) using provisioning user's KV tokenFunction App via Managed Identity at request time
ROTATING CREDENTIALS To rotate Auvik credentials, go to Azure Portal → Key Vault → Secrets → select the secret → New Version → enter the new value. The Function App picks up the new value on the next request — no redeployment or app restart needed. The provisioner does not need to be re-run for credential rotation.
12
ENDPOINTS REFERENCE
ENDPOINTMETHODDESCRIPTIONAUTH REQUIRED
/api/auvikGET / POSTMain proxy endpoint. Forwards requests to Auvik API with injected Basic auth. Replace the Auvik base URL in dashboards with this endpoint.REQUIRE_AUTH setting (default: no)
/api/healthGETHealth check endpoint. Returns a JSON object showing KV secret resolution status and upstream Auvik reachability. Available once Function code is deployed.No
HOW TO TEST THE PROXY DIRECTLY Once function code is deployed, call the proxy endpoint from your browser or Postman:
GET https://{funcapp}.azurewebsites.net/api/auvik/inventory/network/devices
This is equivalent to calling the Auvik API directly but without credentials in the request. The Function App injects the Authorization header server-side.
CONFIGURATION GUIDE
C1
PREREQUISITES
Azure Subscription
An active Azure subscription. The provisioning account must have Contributor or Owner role on the subscription. If you are using a free trial, ensure spending limits are not set — the Consumption plan Function App has no fixed monthly cost but the Storage Account and Key Vault do have minor charges.
Entra ID Permissions
To create an App Registration you need the Application Administrator or Global Administrator role in your Azure AD tenant. Without this, the "New registration" button will be greyed out or missing in the Azure Portal.
Auvik Credentials
A valid Auvik account email and an active API key. Generate the key in Auvik: Account Settings → API Credentials. If the key has not been generated before, Auvik will show a Generate button the first time.
Globally Unique Resource Names
The Storage Account name, Function App name, and Key Vault name must be globally unique across all Azure customers — not just your tenant. If any of the defaults are already taken by another customer, provisioning will fail at that step with a name conflict error. Have alternative names ready.
Modern Browser
Chrome, Edge, or Firefox. MSAL.js requires a browser with popup support. Do not run in a popup-blocking enterprise proxy or in an iframe — MSAL popups will be blocked.
LOCALHOST VS SHAREPOINT REDIRECT URI The App Registration's redirect URI must exactly match the URL where the HTML file is hosted. If you are testing locally (e.g. http://localhost via a local dev server), register http://localhost as the redirect URI. When you move the file to SharePoint, add the SharePoint URL as a second redirect URI on the same app registration. MSAL will use whichever URI matches the current page.
C2
CREATE THE APP REGISTRATION

This is done once in the Azure Portal before opening the provisioner for the first time. All steps below are in Entra ID (Azure Active Directory).

  • 1
    Navigate to App registrations.Azure Portal → search "App registrations" → click New registration.
  • 2
    Set the name.Use cyberadvisers-provisioner or a name that clearly identifies the tool. This appears in your Entra ID app list.
  • 3
    Set supported account types.Select "Accounts in this organizational directory only (Single tenant)." Do not select multi-tenant unless you are provisioning across multiple Azure AD tenants.
  • 4
    Set the redirect URI.Select type: Single-page application (SPA). Enter the URL where the provisioner HTML file will live. If testing locally: http://localhost. If hosted on SharePoint: https://TENANT.sharepoint.com/sites/SITE/Shared%20Documents/azure-provisioner.html
  • 5
    Click Register.The app registration is created. You land on the Overview page.
  • 6
    Copy the IDs.Copy both the Application (client) ID and the Directory (tenant) ID from the Overview page. These go into the provisioner's Step 1 form fields.
  • 7
    Add API permission.In the app registration, go to API permissions → Add a permission → Azure Service Management → Delegated permissions → select user_impersonation → Add permissions.
  • 8
    Grant admin consent.Still on the API permissions page, click "Grant admin consent for [your organization]" and confirm. The permission status changes to a green checkmark. Without this step the login popup will show a consent screen on every sign-in.
ADDING SHAREPOINT AS A REDIRECT URI LATER Once you know the final SharePoint URL, go back to the app registration → Authentication → Add URI under Single-page application. You can have multiple redirect URIs on the same registration — MSAL automatically uses the one matching the current page.
C3
DEPLOY THE HTML FILE

The provisioner is a single self-contained HTML file with one CDN dependency (MSAL.js from Cloudflare CDN). Deploy it anywhere that serves HTML over HTTPS.

SharePoint Document Library
Upload to a document library and click to open. MSAL popup auth works correctly from SharePoint. Make sure the redirect URI in your app registration matches the exact SharePoint URL of the file. If the tenant blocks HTML rendering, convert to .aspx first.
Local Dev Server
Run npx serve . or python -m http.server from the file's directory. Open http://localhost:PORT/azure-provisioner.html. Register http://localhost as the redirect URI in the app registration. MSAL will use the current page URL automatically.
Azure Static Web Apps
The cleanest production host. Place the file in the app root. Add the Static Web App URL as the redirect URI. CDN delivery and HTTPS are automatic.
NEVER OPEN FROM file:// Opening the file directly from your file system (file:///C:/azure-provisioner.html) will cause MSAL to fail. The redirect URI validation in Azure requires an HTTP/HTTPS origin — file:// is not a valid origin. You must use a local server even for local testing.
C4
DEPLOY FUNCTION CODE

The provisioner creates the Azure infrastructure but does not deploy the Node.js function code. The Function App is live in Azure but will return a 404 on all routes until you push code to it. You need the Azure Functions Core Tools installed locally.

  • 1
    Install Azure Functions Core Tools.npm install -g azure-functions-core-tools@4 --unsafe-perm
  • 2
    Create your function project locally.func init my-proxy --worker-runtime node --language javascript
  • 3
    Create the proxy function.func new --name auvik --template "HTTP trigger". Then write the proxy logic: read AUVIK_BASE_URL, AUVIK_API_USER, AUVIK_API_KEY from process.env, build the Basic auth header, forward the request, and return the response. Add CORS headers using the ALLOWED_ORIGIN env var.
  • 4
    Create the health function.func new --name health --template "HTTP trigger". Return a JSON object showing KV secret resolution status (check that env vars are non-empty) and an Auvik API ping result.
  • 5
    Sign in to Azure CLI.az login and az account set --subscription {your-subscription-id}
  • 6
    Publish to the Function App.func azure functionapp publish {your-funcapp-name}. This deploys the code to the Function App created by the provisioner. After a minute the proxy endpoint will respond to requests.
KV REFERENCES REQUIRE MANAGED IDENTITY The AUVIK_API_USER and AUVIK_API_KEY env vars are KV references. They only resolve if the Function App's System Assigned Managed Identity is enabled and has the Key Vault Secrets User (or get secrets) access policy set — both of which the provisioner configures automatically. If process.env values appear as the raw @Microsoft.KeyVault(...) string rather than the actual secret, check Azure Portal → Function App → Identity → System assigned is On.
C5
UPDATE AUVIK CONSOLE DASHBOARDS

Once the Function App is live and the health check passes, update any Auvik console HTML pages that call the Auvik API directly. The change is minimal — swap the base URL and remove the Authorization header.

BEFORE — DIRECT AUVIK CALL (CREDENTIALS IN BROWSER)
const BASE = 'https://auvikapi.us1.my.auvik.com/v1'; const headers = { 'Authorization': 'Basic ' + btoa(AUVIK_USER + ':' + AUVIK_KEY), 'Content-Type': 'application/json' };
AFTER — CALLS PROXY (NO CREDENTIALS IN BROWSER)
const BASE = 'https://{your-funcapp}.azurewebsites.net/api/auvik'; const headers = { 'Content-Type': 'application/json' // No Authorization header — proxy injects it server-side };

The proxy endpoint mirrors the Auvik API path structure. Any call that previously went to https://auvikapi.us1.my.auvik.com/v1/inventory/network/devices now goes to https://{funcapp}.azurewebsites.net/api/auvik/inventory/network/devices. Path, query parameters, and response format are identical.

LOCK DOWN CORS BEFORE PRODUCTION Update the ALLOWED_ORIGIN app setting on the Function App from * to your SharePoint tenant URL. In Azure Portal → Function App → Configuration → Application Settings → find ALLOWED_ORIGIN → edit → save. The Function App restarts automatically. Without this, any website that discovers your proxy URL can use it.
C6
VERIFY & TROUBLESHOOT
  • Step 1 completes with green checkmark. If you see "MSAL init error", the Tenant ID or Client ID is wrong — verify both GUIDs in the Azure Portal app registration Overview page.
  • Sign-in popup opens and returns to the page. If the popup opens but the page doesn't update, the redirect URI in the app registration doesn't match the current page URL. Update Authentication → Redirect URIs in the app registration to match exactly.
  • Subscription dropdown populates. If it stays empty, the ARM token didn't include the right scope. Verify the app registration has Azure Service Management → user_impersonation with admin consent granted.
  • Terminal reaches 100% with all ✓ green lines. Any red error line means a provisioning step failed. Read the error body — it contains the ARM error code and message.
  • Resource Group appears in Azure Portal. Go to portal.azure.com → Resource groups → search for your RG name. All five resources (storage, key vault, consumption plan, function app, and function app plan) should be inside it.
  • Key Vault secrets exist. Azure Portal → Key Vault → Secrets → confirm auvik-api-user and auvik-api-key are present and show as Enabled.
  • Function App Managed Identity is On. Azure Portal → Function App → Identity → System assigned → Status shows On. If Off, the KV references will not resolve and the proxy will fail to read credentials.
  • Health check returns JSON after function code deploy. Click Run Health Check in Step 5. Should return a JSON object. A 404 means code hasn't been deployed yet. A 500 with "KeyVault" in the message means the access policy wasn't applied — check that the Function App's principalId has get-secrets permission on the vault.
TROUBLESHOOTING QUICK REFERENCE
SYMPTOMLIKELY CAUSEFIX
redirect_uri_mismatch error on loginRedirect URI in app registration doesn't match page URLCopy the URL shown at the bottom of Step 1 exactly. Add it to app reg → Authentication → Single-page application URIs.
ARM 403 on resource creationSigned-in account lacks Contributor on the subscriptionAzure Portal → Subscriptions → Access control (IAM) → add Contributor role for the account.
Storage account name conflictDefault name already taken globallyChange the storage account name in Step 3 — add a random suffix like stcyberadvisers4829.
KV secrets stored but app reads raw KV reference stringManaged Identity is Off, or KV access policy wasn't applied for principalIdCheck Function App → Identity (must be On). Check Key Vault → Access policies — Function App identity must have Get on secrets.
Health check 404 after deploymentFunction code not deployed yetRun func azure functionapp publish {funcapp-name} from your local function project directory.
CORS error calling proxy from SharePointALLOWED_ORIGIN is * but browser blocks mixed content, or origin mismatchSet ALLOWED_ORIGIN to your exact SharePoint tenant URL in Function App → Configuration → Application Settings.
Popup blocked during sign-inBrowser popup blocker or enterprise proxyAllow popups for the page URL. MSAL requires popup support — it cannot fall back to redirect mode without code changes.
Provision error on cleanup re-runPrevious partially-created resources conflictDelete the resource group entirely in the Azure Portal (this removes all seven resources), then re-run the provisioner from Step 3.